今天在某个技术群里有网友聊起CSRF攻击,就想起了以前写汤圆网时用到的“盐值”(unique_salt)与token。
一、什么是CSRF攻击及CSRF的防御
可以参考这篇文章:http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
对于用户提交的涉及到修改数据的请求,最好都要考虑下防御CSRF。
二、加盐再散列(salt md5)
参考wiki:https://zh.wikipedia.org/wiki/%E7%9B%90_%28%E5%AF%86%E7%A0%81%E5%AD%A6%29
三、我曾经的解决方案
我也记不得我这个解决方法是哪里学来的了。=。=# 大概思路是这样:
1. 首先定义一个系统全局的salt值:
$config[‘salt’] = ‘abcd1234’;
2. 然后在生成前端页面时,生成timestamp与token:
$timestamp = time();
$token = md5(salt . $timestamp);
3. 前端页面提交表单时候要在POST数据中带上timestamp与token
4. 最后在后端进行验证:
$_POST[‘token’] === md5(salt . $_POST[‘timestamp’])
四、per form or per session
上面“我曾经的解决方案”中,我的csrf token其实是per form的,即每个表单一个csrf token,这种无疑是万无一失的,但实现会比较繁琐,每个表单都要设置csrf token,每个表单提交后都要验证csrf token。
最近在用laravel框架,发现laravel框架的csrf保护方案就比较简单,csrf token是per session,即每个会话只保持有一个csrf token,然后所有post的表单都要验证提交的数据中是否有正确的csrf token。
好像公认的per session的csrf token就够了,虽然安全性比不上per form的,但好在实现简单。