今天抽时间研究了下CSRF攻击,相对于之前的XSS,感觉CSRF更复杂了一些,查阅了一些大佬的博客,在此总结一下:
- 含义:CSRF即跨站点请求伪造(Cross Site Request Forgery),攻击者盗用用户的身份,以用户的名义发送恶意请求,但是服务器端是无法检测出该操作是恶意攻击,因此很多CSRF往往不会被检测出来,通俗点说,就是穿上了用户的“马甲”假装用户进行非法操作。
- 原理:用户通过账户登录某网站时或者离开某网站一段时间(Cookie未过期),攻击者通过某种手段诱惑用户跳转到攻击者所建的钓鱼网站,获取到用户的Cookie信息,然后盗用用户身份,进行非法操作。
- 检测:检测CSRF漏洞是一项比较繁琐的工作,最简单的方法就是抓取一个正常请求的数据包,去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞。通俗来讲,一个组织允许佩戴VIP勋章才可以进入,但是只认勋章不认人,那么如果有人盗用了该勋章,也可以进入该组织。其次一些CSRF检测工具也可以完成检测,例如CSRFTester,CSRF Request Builder等。
- 防御:
- 就像上文所述,只看VIP勋章是远远不足的,需要进行人脸识别,那么如何在HTTP协议中做到“人脸识别”呢?在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址,例如转账,需要用户从登录界面跳转到转账界面,因此referer就会记录下该请求是来源于登录界面,因此在进行转战操作前,只要判断请求的Referer是否来源于登录,如果是的话,可以进行下一步操作,如果是来源于攻击者自己的网站,那么则会拒绝该请求。这种方法看来是简单粗暴,可行性较高,但是也存在一些不足:
(1)Referer 的值是由浏览器提供的,不同的浏览器实现的效果不用,人脸识别还是要依赖于人脸识别器,谁知道会不会出问题。
(2)对于某些浏览器,比如 IE6 或 FF2,目前已经有一些方法可以篡改 Referer 值。如果 登录界面支持 IE6 浏览器,黑客完全可以把用户浏览器的 Referer 值设为以 登录界面域名开头的地址,这样就可以通过验证,从而进行 CSRF 攻击。攻击者直接修改人脸识别器,无论是谁来,都视为VIP成员。
(3)有些网站作为私密网站,不愿意把自己的内网信息公布出来,比如在某公司或者某私密机构中访问该转账网站,就会选择隐藏自己的Referer信息。人戴着口罩来了,人脸识别不出来,总不能把人给赶出来吧。 - 在HTTP参数中加入token参数,该参数是随机生成的,可以在第一次用户登录注册之后添加,然后在接下来每次用户请求之后检验,如果相同,则视为是用户本人。这种方法要比检查 Referer 要安全一些,服务端在收到路由请求时,生成一个随机数,在渲染请求页面时把随机数埋入页面(一般埋入 form 表单内,< input type=“hidden” name="_csrf_token" value=“xxxx”>)
服务端设置setCookie,把该随机数作为cookie或者session种入用户浏览器
当用户发送 GET 或者 POST 请求时带上_csrf_token参数(对于 Form 表单直接提交即可,因为会自动把当前表单内所有的 input 提交给后台,包括_csrf_token)后台在接受到请求后解析请求的cookie获取_csrf_token的值,然后和用户请求提交的_csrf_token做个比较,如果相等表示请求是合法的。但是,在一个网站中,可以接受请求的地方非常多,要对于每一个请求都加上 token 是很麻烦的,并且很容易漏掉,通常使用的方法就是在每次页面加载时,使用 javascript 遍历整个 dom 树,对于 dom 中所有的 a 和 form 标签后加入 token。这样可以解决大部分的请求,但是对于在页面加载之后动态生成的 html 代码,这种方法就没有作用,还需要程序员在编码时手动添加 token。回到人脸识别,检测该人物是否可以进入组织,可以通过第一该成员进入组织后的衣装,姿态等细节来判断,但是细节处理较多,而且该成员在某些方面还不一定与第一次一模一样。另外token还容易被盗取,如果攻击者把自己网站的链接存在网站的留言板等存储区,攻击者可以在通过查看自己的网站的Referer来获取token,以此来发起CSRF攻击。 - 相对于2来说,在源码中指定的标签内加入token无疑需要耗费大量时间和精力,因此,可以在HTTP头部中的XMLHttpRequest 这个类,可以一次性给所有该类请求加上 csrftoken 这个 HTTP 头属性,并把 token 值放入其中。该方法还不用担心token会被盗取,因为XMLHttpRequest 请求的地址不会被记录到浏览器的地址栏中。局限性在于并非所有网站都适用XMLHttpRequest 这个类,而且由于不能被浏览器所记录下,一些用户操作就无法进行,而且为了防御CSRF攻击而把所有请求都改为XMLHttpRequest请求,这也是相麻烦的。