CSRF简单介绍

简介

跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

简单来说,就是我仅仅想让浏览器执行任务A,但是浏览器不仅仅执行了A,还去执行了B,就说明发生了CSRF攻击。很多人会把CSRF和XSS两者混为一谈,XSS的本质是网页有问题,导致了可能会把输入当成代码返回给用户,进而导致浏览器去执行代码;而CSRF是在URL上面做文章。

XSS 利用的是用户对指定网站的信任CSRF 利用的是网站对用户网页浏览器的信任

简单示例

示例1

假设银行转账是通过GET方法直接在url中转账的(当然现实中不可能),A想要转给B一千元,只需要如下的URL即可实现:http://bank.com/transfer.php?by=A&to=B&money=1000,当然银行会首先要求你登陆,发给你一个cookie,当你同时携带着cookie和这个url的时候才会让转账生效。现在假设你已经成功登陆了银行,也就是已经获得了cookie,此时你去访问一个危险网站,这个网站有一段html的代码:<img src=http://bank.com/transfer.php?by=A&to=C&money=1000>,这样如果你是A,那么你就会自动转账1000块钱给C。

示例2

银行觉得这么做实在又蠢又危险,于是决定不用GET而使用POST了。具体代码:

1
2
3
4
5
<form action="transfer.php" method="POST">
  <p> to <input type="text" name="to" /></p>
  <p> money <input type="text" name="money" /></p>
  <p> <input type="submit" value="transfer" /></p>
</form>

这样是不是就能高枕无忧了呢?显然不是的,但是确实如果只使用一个<img>标签是无法得手了,但是可以使用JavaScript来进行编写,照样可以达到一样的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script type="text/javascript">
function bad() {
iframe = document.frames["bad"];
iframe.document.Submit("transfer");
}
</script>

<body onload="bad()">
<iframe name="bad" display="none">
<form method="POST" name="transfer"  action="http://bank.com/transfer.php">
<input type="hidden" name="to" value="C">
<input type="hidden" name="money" value="1000">
</form>
</iframe>
</body>

用JS写了一个bad函数,然后当HTML被加载的时候会使用这个JS函数,而且精心设置了不可见,会自动往目标网站发送POST数据,达成一样的效果。

攻击分类

网上似乎没有对此进行权威的分类,所以我这里只是根据自己的理解给出我的分类。

基于GET方法的攻击

示例1就是这类攻击的典型例子。原因就是一些HTML的标签,包括但是不限于<img> <video>等标签能够允许浏览器去访问指定内容。只要攻击者能够控制这些标签(比如你去访问攻击者的网页),那么就能够发生攻击。

值得一提的是,攻击者并不能够获取到你的cookie,他只是利用了你的cookie

基于POST方法的攻击

示例2就是这种攻击的典型例子,虽然使用了POST方法可以避免第一种攻击,但是攻击者仍然可以构造一个表单,利用JavaScript来进行攻击。原理几乎与GET一致,换汤不换药。有一点需要注意的是,一般会使用不可见的iframe来完成攻击,但是由于有同源策略的保护,所以攻击者通过iframe是无法读取到你真实的内容的,也就是CSRF攻击并不会泄露你的信息(但是攻击者可以修改你的密码,然后登录你的账号来获取你的信息)这点算是不幸中的万幸吧。

防御手段

解决的原则就是:确认确实是用户本人确实想要进行的操作。与此同时,还有很多页面根本就不需要进行CSRF防御,比如仅仅一个展示的页面,压根就没有这个漏洞,也没有这个需求。

以下是三大主要措施:

  • 使用Token。这个防御手段的思想是,使用攻击者无法得知的信息来进行确认。你在正规页面进行的操作,会使用一个token,然后比如你需要修改你的密码,那么网站会问你索要这个token并进行比对(浏览器自动完成,不需要你真的去验证),而如果是你在访问攻击者的网站,它想让你去修改你的密码,但是它无法提供这个token,自然就无法改密了。
  • 当用户执行关键操作的时候,让用户在输入一次密码。因为之前提到CSRF只能利用你的身份,但是它对于你的密码之类一概不知,所以只需要在进行关键操作的时候让用户在输入一次密码,就能轻易解决这个问题了。
  • 验证Referer信息,用户正常请求的referer是正常网页的URL,而非正常请求的referer则是恶意网站的URL。

以下是辅助性的建议措施:

  • 每次用户执行完关键操作(改密之类的),向用户的电子邮箱发送邮件通知用户。
  • 尽量不要使用GET方法
  • 控制cookie的域(这点存疑)