CSRF
是跨站请求伪造(Cross-site request forgery
),也被称为one-click attack
或者session riding
, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
对于CSRF
来说,它的请求有以下两个关键点:
总而言之,攻击者诱导受害者进入第三方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。
例如,目标网站A:www.a.com
,恶意网站B:www.b.com
,目标网站A有一个删除文章的功能,通常是用户单击“删除链接”时才会删除指定的文章,这个链接是www.a.com/blog/del?id=1
,id号代表不同的文章。
我们可以看出,这两个网站的域不一样,利用CSRF
,我们可以这样删除文章:
CSRF
页面(www.b.com/csrf.html
)GET
请求到目标网站A上,例如这样一段代码
www.b.com/scrf.html
页面,攻击发生这个攻击过程有三个关键点:
GET
请求javascript
参与GET /blog/del?id=1 HTTP/1.1
Host: www.a.com
User-Agent: ...
Connection: keep-alive
Referer: http://www.b.com/csrf.html
cookie: ...
如果是用户自己点击删除链接时发出的请求会类似于这样:
GET /blog/del?id=1 HTTP/1.1
Host: www.a.com
User-Agent: ...
Connection: keep-alive
Referer: http://www.a.com/blog/
cookie: ...
可以看到两个请求中,除了请求来源Referer
不一样外,其他都一样,尤其是cookie
值,该cookie
是用户登录目标网站A后的身份认证标志。跨站发出的请求也同样会带上目标网站A的用户cookie
,这样的请求就是身份认证后的,攻击才会成功。
按照请求类型来区分,可以分为GET
型和POST
型。
GET
类型在攻击过程中有所介绍,GET
类型是较为容易攻击的一种方式,只需要一个http
请求,攻击者一般会这样操作:
<img src="http://www.a.com/blog/del?id=1" />
在受害者访问这个img
后,浏览器会自动向www.a.com
发起HTTP
请求。www.a.com
就会收到包含受害者登录信息的一次跨域请求。
这种类型的CSRF
攻击通常使用的是一个自动提交的表单,如:
<form action="http://www.a.com/submit" method=POST>
<input type="hidden" name="account" value="xiaoming" />
<input type="hidden" name="amount" value="10000" />
<input type="hidden" name="for" value="hacker" />
form>
<script> document.forms[0].submit(); script>
访问该页面后,表单会自动提交,相当于模拟用户完成了一次POST
操作。
POST
类型的攻击通常比GET
要求更加严格一点,但仍并不复杂。任何个人网站、博客,被黑客上传页面的网站都有可能是发起攻击的来源,后端接口不能将安全寄托在仅允许POST
上面。
HTML
中能够设置src/href
等链接地址的标签都可以发起一个GET
请求,例如:
<link href="">
<img src="">
<iframe src="">iframe>
<script src="">script>
<embed src="">
<a href="">a>
<video src="">video>
<audio src="">audio>
...
CSS
样式中的:
@import ""
background: url("")
...
还有通过js动态生成的标签对象或CSS
对象发起的GET
请求,而POST
请求只能通过form
提交方式。
JSON Hijacking
技术非常经典,攻击过程是CSRF
,不过是对AJAX
响应中最常见的JSON
数据类型进行的劫持攻击。很多时候,网站发出的AJAX
请求,响应回来的是JSON
格式的数据。
Flash
的世界同样遵循同源策略,通过ActionScript
脚本来发起攻击。一般有以下两点:
allow-access-from domain="*"
,表示允许任何域的Flash
请求本域的资源。如果用户登录目标网站,被欺骗访问包含恶意Flash
网页时,自己的隐私数据就可能被盗走。GET/POST
请求对浏览器是合法的,在Flash
也一样。利用CSRF
,可以造成以下危害:
CSRF
蠕虫既然CSRF
大多来自第三方网站,那么我们就直接禁止外域(或者不受信任的域名)对我们发起请求。
请求头有Origin Header
、Referer Header
,这两个Header
在浏览器发起请求时,大多数情况会自动带上,并且不能由前端自定义内容。 服务器可以通过解析这两个Header
中的域名,确定请求的来源域。
在部分与CSRF
有关的请求中,请求的Header
中会携带Origin
字段。字段内包含请求的域名(不包含path
及query
),如果Origin
存在,那么直接使用Origin
中的字段确认来源域名就可以。
但是Origin
在以下两种情况下并不存在:
IE11
同源策略:IE11
不会在跨站CORS
请求上添加Origin
标头,Referer
头将仍然是唯一的标识。最根本原因是因为IE11
对同源的定义和其他浏览器有不同。Origin
不包含在重定向的请求中,因为Origin
可能会被认为是其他来源的敏感信息。对于302重定向的情况来说都是定向到新的服务器上的URL
,因此浏览器不想将Origin
泄漏到新的服务器上。根据HTTP
协议,在HTTP
头中有一个字段叫Referer
,记录了该HTTP
请求的来源地址。 对于Ajax
请求,图片和script
等资源请求,Referer
为发起请求的页面地址。对于页面跳转,Referer
为打开页面历史记录的前一个页面地址。因此我们可以通过检查referer
判定是否为本站的请求。
但缺点是浏览器可以关闭referer
,且低版本的浏览器会存在伪造Referer
的风险。因此,服务器的策略是优先判断Origin
,如果请求头中没有包含Origin
属性,再根据实际情况判断是否使用Referer
值,从而增加攻击难度。
token
是最普遍的一种防御方法,后端先生成一个token
,之后将此放在数据库中并发送给前端,那么前端发送请求时就会携带这个token
,后端通过校验这个token
和数据库中的token
是否一致,以此来判断是否是本网站的请求。