CSRF主要利用受害者尚未失效的身份认证信息(Cookie、会话等),诱骗其点击恶意链接或者访问包含攻击代码的页面,在受害人不知情的情况下以受害者的身份向(身份认证信息所对应的)服务器发送请求,从而完成非法操作(如转账、改密等)。

0x00 漏洞本质

其一、CSRF可以攻击成功的本质原因是因为请求的所有重要参数都可以被攻击者预测。

其二、被攻击者在不知情的情况下身份认证信息(Cookie)被使用了。

由上面两点我们可知,如果我们能够知道一个请求消息的所有参数,参数的值可以进行伪造,且被害者本地有认证信息(本地Cookie或临时Cookie),那么我们把该请求消息诱骗被害者来点击/提交,就能完成攻击。

Cookie通常用来进行用户身份认证及状态记录。

Cookie可以分为两种:

  • Session Cookie:又叫临时cookie。
  • Third-party Cookie:又叫本地Cookie。

当Set-Cookie时,若指定了expire时间,在expire时间超时之前,都将被存储在本地,就叫本地Cookie。

当Set-Cookie时,若没有指定expire时间,仅存在于浏览器的程序的生命周期内,保存在浏览器进程的内存中,关闭浏览器后失效(新建tab页不会失效)。此时就是临时Cookie。

0x02 浏览器Cookie策略

Cookie是在发起请求时浏览器自动携带在请求消息中的。

对于一些跨域请求操作,一些浏览器处于安全考虑,默认会禁止在跨域请求时携带本地Cookie(临时Cookie不限制)。

  • 默认会禁止的浏览器:IE6/7/8、Safari等。
  • 默认不会禁止的浏览器:Firefox、Chrome、Android等。

对于<a><script><link><img><iframe>等标签都可以进行跨域请求资源。

因此,对于禁止在跨域请求时携带本地Cookie的情况下,攻击更复杂,比如需要让受害者先访问目标站点并进行了身份认证,让浏览器中先存在临时Cookie。对于没有禁止的环境下,只要受害者本地存储有Cookie,就能完成攻击。

0X03 GET与POST提交数据

若存在CSRF漏洞的功能点是以GET方式提交数据,只需要修改GET请求链接内容然后让用户点击即可完成攻击。

若存在CSRF漏洞的功能点是以POST方式提交数据,我们需要在我们的服务器上创建一个提交数据的表单页面,然后让用户访问该页面。

0x04 CSRF防御

防御的思路围绕CSRF的本质考虑。

1. 验证码

对某些重要的操作,使用验证码验证,验证码一方面避免了身份认证信息在不知情的情况下被使用(因为与服务器有交互),另一方面攻击者在不知道验证码参数的值也无法完成攻击。

缺点就是用户体验会很差,因为每次操作都需要输入验证码。因此作为辅助的防御手段。

2. Referer Check

在HTTP请求消息头中有一个Referer头部,该头部的值记录着是从哪个页面(URL)跳转过来的。

通过对消息Referer头部进行检查,也可以对CSRF防御起到一定的作用。

缺点是服务器不是任何时候都能获取的Referer的值,有时候出于安全考虑,限制了Referer的发送。

3. Token

Token是一串足够长且复杂的随机数,Token防御CSRF的本质就是让请求参数不可被预测,不能被预测也就意味着攻击者不能构造出恶意数据包请求。

逻辑:

当客户端访问页面时,服务器会生成Token,然后把Token值存储在Session中,并且在返回的表单页面中也会嵌入一个隐藏的<input />标签,标签的value属性值即为Token值。当用户填写表单提交数据时,Token也会自动被作为参数提交,服务器会先将提交过来的Token与Session中存储的Token做对比验证。

针对CSRF的防御,如今一致的选择都是Token,但是使用Token也要注意一些安全准则:

  • Token在使用后要及时销毁,避免被重复使用。
  • Token参数尽可能采用POST方式提交,因为GET方式会将其放到URL中,可能会被Referer头部泄露。
  • 若页面同时还存在XSS漏洞,那么Token防御将变得没有作用,因为XSS可以先读取到页面的Token再构造请求,即XSRF。

最后更新: 2019年05月21日 11:30

原始链接: https://sakuxa.com/2019/03/25/CSRF/