CSRF(Cross-site request forgery跨站请求伪造,也被称成为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。

1 CSRF原理介绍
一、CSRF×××原理
CSRF×××原理比较简单,如图1所示。其中Web A为存在CSRF漏洞的网站,Web B为×××者构建的恶意网站,User C为Web A网站的合法用户。

                                                        1、浏览并登陆网站A
                                                        2、验证成功,生成cookie
                                                        5、访问A,并执行B的恶意代码

user C-------浏览器--------------------------------------webA

                                                                    3、访问恶意网站B
                                                                    4、B要求访问A

user C-------浏览器--------------------------------------webB

                        图1 CSRF原理
  1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
    2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
  2. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
  3. 网站B接收到用户请求后,返回一些×××性代码,并发出一个请求要求访问第三方站点A;
  4. 浏览器在接收到这些×××性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。

2 CSRF漏洞防御

CSRF漏洞防御主要可以从三个层面进行,即服务端的防御、用户端的防御和安全设备的防御。
2.1 服务端的防御
2.1.1 验证HTTP Referer字段
根据HTTP协议,在HTTP头中有一个字段叫Referer,它记录了该HTTP请求的来源地址。在通常情况下,访问一个安全受限页面的请求必须来自于同一个网站。比如某银行的转账是通过用户访问http://bank.test/test?page=10&userID=101&money=10000页面完成,用户必须先登录bank.test,然后通过点击页面上的按钮来触发转账事件。当用户提交请求时,该转账请求的Referer值就会是转账按钮所在页面的URL(本例中,通常是以bank. test域名开头的地址)。而如果×××者要对银行网站实施CSRF×××,他只能在自己的网站构造请求,当用户通过×××者的网站发送请求到银行时,该请求的Referer是指向×××者的网站。因此,要防御CSRF×××,银行网站只需要对于每一个转账请求验证其Referer值,如果是以bank. test开头的域名,则说明该请求是来自银行网站自己的请求,是合法的。如果Referer是其他网站的话,就有可能是CSRF×××,则拒绝该请求。

2.1.2 在请求地址中添加token并验证
CSRF×××之所以能够成功,是因为×××者可以伪造用户的请求,该请求中所有的用户验证信息都存在于Cookie中,因此×××者可以在不知道这些验证信息的情况下直接利用用户自己的Cookie来通过安全验证。由此可知,抵御CSRF×××的关键在于:在请求中放入×××者所不能伪造的信息,并且该信息不存在于Cookie之中。鉴于此,系统开发者可以在HTTP请求中以参数的形式加入一个随机产生的token,并在服务器端建立一个拦截器来验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF×××而拒绝该请求。
2.1.3 在HTTP头中自定义属性并验证
自定义属性的方法也是使用token并进行验证,和前一种方法不同的是,这里并不是把token以参数的形式置于HTTP请求之中,而是把它放到HTTP头中自定义的属性里。通过XMLHttpRequest这个类,可以一次性给所有该类请求加上csrftoken这个HTTP头属性,并把token值放入其中。这样解决了前一种方法在请求中加入token的不便,同时,通过这个类请求的地址不会被记录到浏览器的地址栏,也不用担心token会通过Referer泄露到其他网站。

3 其他防御方法

  1. CSRF×××是有条件的,当用户访问恶意链接时,认证的cookie仍然有效,所以当用户关闭页面时要及时清除认证cookie,对支持TAB模式(新标签打开网页)的浏览器尤为重要。
  2. 尽量少用或不要用request()类变量,获取参数指定request.form()还是request. querystring (),这样有利于阻止CSRF漏洞×××,此方法只不能完全防御CSRF×××,只是一定程度上增加了×××的难度。