【发布时间】:2023-03-23 15:22:01
【问题描述】:
我正在学习如何使用反 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 等值?
任何想法都将不胜感激。
【问题讨论】: