CSRF攻击通过利用浏览器Cookie,使得Trusted.com误以为请求来自于Alice。那么除了Cookie外,我们是不是可以再加一层验证来保护Alice呢?
有过网站开发经验的同学应该记得网站里经常出现csrf_token,这个token就是服务器在Cookie之外的第二层验证。常见csrf_token使用方式有两种:
对于每个request,在服务器端生成一个新的csrf_token,并将其返回在页面的表单中。在服务器端每次接收到请求时,都会验证表单中是否包含正确的csrf_token。由于第三方网站无法得知正确的csrf_token,所以无法进行csrf攻击。
get_token = get_random_token() return { <form> <input name=field1></input> <input type='hidden' name='csrfmiddlewaretoken' value=#{get_token()} /> </form> }
这个方法的好处是客户端不需要支持javascript,因此通用于所有的网站。坏处是由于服务器端对于每个请求都会更换csrf_token,因此他需要保证用户提交的表单是用户最近一次请求的表单。如果用户通过多个tab同时浏览该网站,那么往往会导致用户提交的表单不是最新的那一个。
第二个方法是为每个session生成一个csrf_token,随后将csrf_token保存到cookie中,之后通过javascript在每次请求时将csrf_token设置到http header中的X-Csrf-Token属性中。再在服务器端比较Cookie的csrf_token与header中的token是否一致。
//当用户登录时设置CookieSet-Cookie: Csrf-token=i8XNjC4b8KVok4uw5RftR38Wgp2BFwql; expires=Thu, 23-Jul-2015 10:25:33 GMT; Max-Age=31449600; Path=///当用户发送请求时设置Http Header中的X-Csrf-TokenX-Csrf-Token: i8XNjC4b8KVok4uw5RftR38Wgp2BFwql
有些读者可能会问如果设置在Cookie中,那么Malicious.com岂不是可以利用Cookie中的值来设置X-Csrf-Token的值么?
其实尽管可以从Malicious.com发送给Trusted.com带有含有csrf_token的Cookie,但是根据同源策略,Javascript无法从Malicious.com读取或者写入Trusted.com的Cookie。所以Malicious.com无法知道正确的csrf_token是什么,也不能够正确的修改Http-Header的X-Csrf-Token属性。
现在很多常见的web开发框架都默认的使用Cookie-to-header方法,比如Django, Rails, Angularjs。
比如Firefox有个插件将受信任的网站和不信任的网站区分对待。然后当用户从不受信任的网站往受信任的网站发送信息时,将验证信息移除。
服务器端通过检查请求是否来自受信赖的网站来判断请求是否可信。不过这个方法也有问题。有些浏览器出于隐私方面的考虑,会移除掉referer header。
这是比较原始的防御手段。原理是最初大量的CSRF攻击是通过带有src的图片的,发送get请求来发动CSRF攻击。所以很多服务器对于数据相关的请求改为只接受post请求。不过这个防御手段并没有什么用,因为攻击者可以轻松的使用javascript来模拟post请求。
联系客服