八、跨站请求伪造
作者:Peter Yaworski
译者:飞龙
描述
跨站请求伪造,或 CSRF 攻击,在恶意网站、电子邮件、即使消息、应用以及其它,使用户的 Web 浏览器执行其它站点上的一些操作,并且用户已经授权或登录了该站点时发生。这通常会在用户不知道操作已经执行的情况下发生。
CSRF 攻击的影响取决于收到操作的站点。这里是一个例子:
- Bob 登录了它的银行账户,执行了一些操作,但是没有登出。
- Bob 检查了它的邮箱,并点击了一个陌生站点的链接。
- 陌生站点向 Bob 银行站点发送请求来进行转账,并传递第一步中,保存 Bob 银行会话的 Cookie 信息。
- 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 代码可以用于代表任何未知受害者提交表单。
<html>
<head><title>csrf</title></head>
<body onLoad="document.forms[0].submit()">
<form action="https://app.shopify.com/services/partners/api_clients/1105664/\ export_installed_users" method="GET">
</form>
</body>
</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 进行调用:
GET /auth/twitter/disconnect HTTP/1.1
Host: twitter-commerce.shopifyapps.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:43.0) Gecko/2010010\ 1 Firefox/43.0
Accept: text/html, application/xhtml+xml, application/xml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://twitter-commerce.shopifyapps.com/account
Cookie: _twitter-commerce_session=REDACTED
Connection: keep-alive
由于浏览器进行 GET 请求来获取给定 URL 处的图片,并且不验证任何 CSRF Token ,用户的商店现在已断开连接:
<html>
<body>
<img src="https://twitter-commerce.shopifyapps.com/auth/twitter/disconnect">
</body>
</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
值。更好的是,这个文件可以由攻击者任意读取,而不需要受害者做什么,除了浏览这个恶意页面。这里是它提供的代码。
<html>
<head>
<title>Badoo account take over</title>
<script src=https://eu1.badoo.com/worker-scope/chrome-service-worker.js?ws=1></script>
本质上,当受害者加载此页面时,它会调用 Badoo 的脚本,为用户获取rt
参数,之后代表受害者进行调用,这里,它将受害者的账户链接到了攻击者的,本上上完成了账户的控制。
重要结论
无风不起浪。这里,攻击者注意到了
rt
参数在不同位置返回,特别是 JSON 响应,因此,它正确猜测了,它可能出现在一些可以利用的地方,这里是 JS 文件。继续干吧,如果你觉得一些东西可能会发生,一定要继续挖掘。当你访问目标站点或应用时,使用 Burp 检查所有被调用的资源。
总结
CSRF 表示另一个攻击向量,并且可能在受害者不知道,或者不主动执行操作的情况下发生。CSRF 漏洞的发现可能需要一些机智,同样,也需要测试任何东西的渴望。
通常,如果站点执行 POST 请求,Web 表单都统一由应用框架保护,例如 Rails,但是 API 又是另外一个事情。例如, Shopify 使用了 RoR 编写,它对所有表单默认提供了 CSRF 保护(当然也可以关掉)。但是,显而易见,这对于使用框架创建的 API 不一定成立。最后,一定要观察任何通过 GET 请求执行的,修改服务器数据的调用(例如删除操作)。