我正在学习如何使用反 CSRF 令牌来防止 CSRF。本质上,这个想法是:-
1) 生成一个令牌,例如 Md5 或 Sha1,然后将此值存储在会话变量中:-
$token = md5(uniqid(rand(), TRUE));
$_SESSION['token'] = $token;
2) 所有表单都在 POST 隐藏字段中包含此令牌值
<input type='hidden' name='token' value='$nonce_token' />
例如,在源代码中用户会是什么样子:-
<input type='hidden' name='token' value='9ee66e4e63a06ee4b83a3edde4ecd587' />
3)一旦发送表单,检查 POST 隐藏字段令牌值是否与存储在会话值中的令牌匹配
if($_POST['token']==$_SESSION['token']){...ok...}
然而,这个过程似乎有点缺陷,因为通过在隐藏的 POST 字段中包含令牌值,攻击可以简单地查看网站源代码以查看令牌,然后将其包含在我的应用程序将因此而生成的恶意 POST 表单中一旦收到作为发送的令牌值成功将匹配我的会话变量中的令牌值,因为我基本上向攻击者显示我的隐藏字段中的令牌值。
因此,我的问题是最好的解决方法是什么,因为我的一些想法似乎仍然没有什么缺陷:-
1) 改用 _GET 但这仍然有 _POST 之类的缺陷
2) 在 x 分钟或每个请求后更改令牌值,但在返回浏览器时会导致可用性问题或在用户填写表单时失败,并且令牌值与更新的会话令牌值相比会变得过时,因为隐藏令牌值不会在用户更新时更新填写表格。
3)尝试加密隐藏的 POST 表单令牌值,然后在发送 POST 时解密,但加密/解密已经散列的值似乎很复杂,尤其是一种加密方式具有 MD5 等值?
任何想法将不胜感激。