【译】Cross Site Request Forgery(CSRF)
FrankKai opened this issue · comments
- 概览
- 描述
- 预防措施并不起作用
- 使用安全的cookie
- 只允许POST请求
- 多步骤数据处理
- URL重写
- HTTPS与CSRF
- CSRF攻击是如何工作的?
- Get场景
- Post场景
- 其他HTTP方法
概览
CSRF全称为Cross-Site Request Forgery
,是一种强制用户在已经鉴权过的网站上执行用户不希望做的操作的攻击。通过一些社会工程学的帮助(例如通过email或者chat方式发送一个链接),攻击者可以欺骗网站的用户去执行攻击者选择的操作。如果受害者是一个普通的用户,一个成功的CSRF攻击可以强制用户去执行状态变更请求,例如资金交易,email地址变更等等。如果受害者拥有管理员权限,CSRF攻击会危及整个web应用。
描述
CSRF是一种欺骗受害者去提交恶意请求的一种攻击。它会使用受害者已有的认证和权限,去执行一个受害者个人名义的未知的函数。对于大多数网站来说,浏览器请求会自动带上和当前网站相关的凭证,例如用户session的cookie,IP地址,窗口域名凭证等等。因此,如果用户已经在网站鉴权成功,网站就没有办法去区分出由攻击者发出的伪造的请求和受害者发出的合法请求。
CSRF攻击会让服务器的状态发生变更,例如改变受害者邮箱地址或者密码,或者支付一些东西。强制受害者去查询一些内容对攻击者没有好处因为攻击者无法获取到响应,但是受害者可以。CSRF主要用来攻击可以导致状态变更的请求。
很多时候是网站本身存在CSRF漏洞。例如”存储CSRF flaws“。可以通过存储一个IMG或者IFRAME标签并且去接受HTML内容,或者是一种更加复杂的XSS攻击。如果攻击可以在网站存储CSRF攻击,袭击程度就真的很严重了。事实上,这种可能性增加是因为受害者更可能去访问互联网上的一个包含CSRF攻击的随机网页。另外一种是因为受害者已经在网站取得了权限。
同义词:XSRF、Session Riding、Cross-Site Reference Forgery、Hostile Linking、One-Click attack(Microsoft)
预防措施并不起作用
使用secret cookie
谨记所有cookie,甚至是秘密cookie,都可以被所有请求提交。鉴权token是否提交取决于用户是否触发请求。session认证器会将请求与一个指定的session对象关联起来。session认证器不会去验证用户是否要提交请求。
只使用POST请求
应用可以被设计成只使用POST请求去指定业务逻辑。会有人误解因此攻击者无法构建一个恶意链接,一次CSRF攻击无法被执行。不幸的是,这种想法是错的。攻击者有很多方式去触发一个伪造的POST请求,例如攻击者在网站上增加了一个隐藏的form表单。这个表单可以通过js自动触发或者是受害者觉得这个链接可以做点什么自己去点。
有很多有缺陷的防止CSRF攻击的方式出现,我们建议你不要这样做。
多步骤数据处理
多步骤数据处理不能抵挡CSRF攻击。只要攻击者能预测到或者推断出完整处理过程的每一步,CSRF攻击有效。
URL重写
这看起来是一个比较安全的CSRF防御技术,这样攻击者就猜不到受害者的session ID了。然而用户的session ID暴露在URL上。我们不建议为了防御一个攻击而又引入另外一个攻击。
HTTPS
HTTPS本身不需要防御CSRF攻击。
然而,应该被认为是任何预防措施值得信任的先决条件
CSRF攻击是如何工作的?
有很多种方式骗一个用户去加载表单信息或者向一个web应用提交信息。为了执行攻击,我们必须首先理解如何生成一个有效的怀有攻击用户的恶意的请求。我们可以根据这个例子去理解:假设Alice想用bank.com向Bob转账100美元,而这个网站可以很轻易的被CSRF攻击成功,攻击者Maria想把转账目标从”Bob“换成”Maria“,也就是想让Alice把钱转给自己。这个攻击由一下几步组成:
- 构建一个将要利用的URL或者script
- 通过社会工程学去触发Alice执行动作
Get场景
如果应用被设计成主要使用GET请求去传输参数并且执行操作的话,转账操作可以缩减成这样的链接:
GET http://bank.com/transfer.do?acct=BOB&amount=100 HTTP/1.1
Maria现在想要利用网站的漏洞攻击Alice。Maria首先伪造URLAlice给Maria转账10万美元。Maria获取到原始的URL替换了名字,修改了金额,改成这样的链接:
GET http://bank.com/transfer.do?acct=MARIA&amount=100000 HTTP/1.1
社会工程学手段引导Alice在登录银行应用时加载这个伪造的URL。通常可以通过这样的方式去做:
- 发送一个来路不明的HTML内容
- 种植一个伪造的URL或者脚本,放在受害者访问网上银行页面的类似的位置上
伪造的URL可以被未造成一个普通的链接,并且诱导受害者去点击:
<a herf="http://bank.com/transfer.do?acct=MARIA&amount=100000">View my Pictures!</a>
或者是一个0*0的假图:
<img src="http://bank.com/transfer.do?acct=MARIA&amount=100000" width="0" height="0" border="0">
如果这个图片在email中,Alice看不到任何内容。然而,浏览器会在不给出任何提示的情况下,执行这个伪造的请求。
一个真实的例子就是2008年的uTorrent漏洞,它被用于大规模下载恶意软件。
Post场景
在GET和POST攻击之间的唯一不同就是受害者执行攻击的方式不同。假设银行使用POST请求伪造了一个如下请求:
POST http://bank.com/transfer.do HTTP/1.1
acct=BOB&amount=100
这样的请求不能通过A或者IMG标签发送出去,但是可以使用FORM标签发送出去:
<form action="http://bank.com/transfer.do" method="POST">
<input type="hidden" name="acct" value="MARIA">
<input type="hidden" name="amount" value="100000">
<input type="submit" value="View my pictures">
</form>
诱导的方式需要手动点击按钮才可以进行攻击,还有一种通过js自动执行的方式。
<body onload="document.forms[0].submit()">
其他HTTP方法
现代的web应用api会频繁使用其它的HTTP方法,例如PUT或者DELETE。假设有安全漏洞的银行使用PUT推送一个JSON快作为入参:
PUT http://bank.com/transfer.do HTTP/1.1
`{"acct": "BOB", "amount": 100 }`
这样的请求可以被嵌入到一个伪页面去执行:
<script>
function put() {
var x = new XMLHttpRequest();
x.open("PUT","http://bank.com/transfer.do",true);
x.setRequestHeader("Content-Type", "application/json");
x.send(JSON.stringify({"acct":"BOB", "amount":100}));
}
</script>
<body onload="put()">
幸运的是,这个请求不会被现代浏览器执行,因为现代浏览器有same origin policy策略。这个策略会默认开启,除非目标网站主动明确通过CORS请求头Access-Control-Allow-Origin: *
去将攻击者的网站加入白名单网站。