我想知道以下方法是否会完全阻止 CSRF,并与所有用户兼容。
这里是:
在表单中只包含一个额外的参数,即:encrypted(user's userID + request time)
. 服务器端只需解密并确保它是正确的用户 ID 并且请求时间是最近的。
除了有人嗅探用户的流量或破坏加密之外,这是否完全安全?有什么缺点吗?
虽然您的方法是安全的,但它不是标准的。防止 CSRF 攻击的标准方法是生成包含在隐藏字段和 cookie 中的伪随机数,然后在服务器端验证这两个值是否匹配。看看这个帖子。
一个主要的缺点是,如果用户在发布表单之前打开浏览器的时间超过了您认为合理的时间范围,您的页面将“超时”。我更喜欢网站不要催促他们的用户执行他们的操作,除非该操作本质上是时间敏感的。
它并不完全安全,因为攻击站点可能会猜测用户 ID。
如果您使用每会话加密密钥,它是安全的。(但是你需要做的就是发送原始密钥,它已经很安全了)
另外,请记住时区和不准确的时钟。
它应该工作,是的。虽然我建议您在创建新用户时为 UserID 使用随机数,而不是简单的递增数字(显然,在创建用户时确保它是唯一的)。这样,攻击者就很难“猜测”。
拥有 UserID 和 DateTime 是一个开始,但您还需要一个伪随机数值,最好在金丝雀令牌中添加高熵。基本上,您需要在给定上下文中降低页面中令牌的可预测性。理论上,只有 UserID 和 DateTime 可能会在一段时间后中断,因为它不够“随机”。话虽如此,CSRF 攻击通常是脚本化的,而不是直接监控的,因此根据您的应用程序的暴露程度,这可能就足够了。
此外,请务必使用更安全的加密算法,例如Rijndael/AES,其密钥位足以保证应用程序的安全性,并使用伪随机初始化向量。
您提出的安全系统容易受到攻击。
像 AES 这样的分组密码通常用作非常安全的随机数生成器。它们被称为CSPRNGs。但是,与任何随机数生成器一样,您必须担心您为算法播种的内容。在这种情况下,您正在使用user's userID + request time
攻击者可以知道的两者,您的实现没有密钥或 IV,因此我假设它们为 NULL。攻击者正在构建请求,因此他将始终知道request time
. 这userId
可能是一个主键,如果你有 100 个用户,那么攻击者可以伪造 100 个请求,其中一个会起作用。但是攻击者可能只是想强制管理员更改他的密码,管理员的主键通常是 1。
不要重新发明Wheal,已经构建了非常好的随机数生成器,并且还有反 csrf 库。