如何防止 PHP、csrf、xsrf 中的表单重放/中间人攻击
我有一个网络表单,并且正在使用 PHP。我知道表单可以被操纵(我相信这称为重放攻击或中间人攻击)。所以我想使用一些真实性令牌作为隐藏字段。
我知道的威胁可能性是:
- 攻击者劫持合法用户的表单(我认为这是中间人攻击)
- 合法用户本身就是攻击者:他获取表单,读取令牌,但使用它发送危险数据(我认为这是重放攻击)
在我回答问题之前,如果我到目前为止所说的任何内容不正确,请纠正我,因为也许我的理解有缺陷。
现在的问题是:
- 生成此令牌的最佳实践是什么,以便没有它的表单被拒绝(例如,加盐?)。
- 人们如何确保令牌不被重放。
基于评论的新小问题:
- 会话劫持与中间人攻击相同吗?
I have a web form and I'm using PHP. I'm aware that forms can be manipulated (I believe it's called replay attack or a man-in-the-middle attack). So I'd like to use some authenticity token as a hidden field.
The threat possibilities that I'm aware of are:
- Attacker hijacks the legitimate user's form (this I believe is the man-in-the-middle attack)
- the legitimate user is himself the attacker: he gets the form, reads the token but uses it to send dangerous data (this I believe is the replay attack)
Before I get to the questions, please correct me if anything I said so far is incorrect, because maybe my understanding is flawed.
Now to the questions:
- What is the best practice to generate this token so that the form without it gets rejected (for example, salting?).
- What do people do to make sure that the token isn't being replayed.
New small questions based on comments:
- Is session hijacking the same as man-in-the-middle attack?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您在标题中提到了 CSRF,但在您的问题中并未真正涵盖它。
您可以在线阅读详细信息,但 CSRF 基本上是一种攻击,允许合法的用户在不知情的情况下提交到网站。例如,如果 SO 不能防止此类攻击,我可以制作一个表单,当您单击我的这个不良表单时,会导致您的 SO 配置文件信息发生更改,并期望发生其他情况(“赢得一百万美元!点击这里!!”)。此表单将使用您的浏览器 cookie 对您进行身份验证,并让您认为您正在合法提交个人资料更新。
为了防止这种情况,您确实需要做几件事:
第二项的替代方法是检查引荐来源网址是否始终是您的网站或您期望发布 POST 的网站。我不鼓励非 HTTPS 站点这样做,因为某些浏览器/网络硬件会删除引荐来源网址,并且引荐来源网址的存在并不总是可靠的。
You mentioned CSRF in the title but didn't really cover it in your question.
You can read about it in detail online, but CSRF is basically an attack that lets a legitimate user submit to a site unknowingly. For instance, if SO wasn't protecting against such attacks, I could craft a form that causes your SO profile information to be changed when you click on this bad form of mine, expecting something else to happen ("Win a Million bucks!! Click here!!"). This form would use your browser cookies to auth you with SO and make it appear to SO that you were legitimately submitting updates to your profile.
To protect against this, you really want to do a couple of things:
An alternative to that second item is to check that the referrer is always your site or a site you expect the POST from. I don't encourage this for non-HTTPS sites because some browsers/networking hardware strip out referrers, and it's not always reliable that a referrer exists.
用于生成令牌的方法并不是非常重要。 重要的是令牌只能使用一次。在用户会话中保留为用户生成的令牌列表。如果用户提交表单并且提交的令牌不在会话中,您可以拒绝该表单。
防范中间人有点困难。我见过的一种常见技术是将所有隐藏表单字段包含在哈希函数中以生成令牌,然后根据已知的隐藏字段重新生成令牌。然而,这只能防止隐藏的领域操纵,这可能不是中间人的最终目标。
当用户成功提交带有令牌的表单时,从会话中删除令牌,因此该提交的任何重播都会失败。然而,所需要的只是用户再次请求表单来生成另一个令牌。然后可以在后续的自动攻击中使用该新令牌。 换句话说,表单令牌对于对抗 CSRF 很有用,但对于对抗自动重放和中间人攻击却不是非常有效。
同样,您将希望调整您的应用程序以不需要用户在表单上使用后退按钮。如果他们的提交存在问题,您将需要将填写了数据的表单返回给用户。如果用户点击后退按钮来更正错误,她的提交将因现在无效而失败令牌。
另外,坦率地说,当您需要担心请求重放和中间人攻击时,您的用户连接已经受到损害,并且您可能无能为力来减轻任何损害。仅 SSL 就足以针对 MITM 和重放提供足够的保护级别,如果您担心这一点,那么您将在 SSL 下运行......
The method used to generate the token is not highly important. The important thing is that the token gets to be used only once. Keep a list of tokens generated for the user in the user's session. If the user submits a form and the token submitted isn't in the session, you can reject the form.
Protecting against man-in-the-middle is a little difficult. A common technique I've seen is including all of the hidden form fields in the hash function to generate the token, and then regenerating the token based on known hidden fields. However, that would only protect against hidden field manipulation, which may not be the ultimate target of the man in the middle.
When the user successfully submits a form with the token, delete the token from the session, so any replay of that submission will fail. However, all it takes is the user requesting the form again to generate another token. That new token can then be used in subsequent automated attacks. In other words, form tokens are useful against CSRF, but not highly effective against automated replay and man-in-the-middle attacks.
Likewise, you're going to want to adapt your application to not require the use of the user's back button on forms. If there's an issue with their submission, you're going to need to return the form back to the user with their data filled in. If the user hits her back button to correct the error, her submission will then fail due to the now invalid token.
Also, to be frank, by the time you need to worry about request replays and man-in-the-middle attacks, your user's connection has already been compromised, and there's probably not much you can do to mitigate any damage. SSL alone is an adequate protection level against MITM and replay, and if you're that worried about it, you'll be running under SSL...
为了生成该令牌,我使用了一种似乎效果很好的策略。
To generate that token, here's a strategy I use that seems to work well.
csrf-magic 是 CSRF 令牌的一个很棒的类,它会自动将它们放入您的页面
http://csrf.htmlpurifier.org/
“csrf-magic 使用 PHP 的输出缓冲功能动态重写文档中的表单和脚本。它还将拦截 POST 请求并检查其令牌(使用各种算法;一些生成随机数,一些生成用户特定的令牌)这意味着,对于带有表单的传统网站,您可以将 csrf-magic 放入您的应用程序中,然后就不用管它了!”
csrf-magic is a great class for CSRF tokens, it puts them into your page automatically
http://csrf.htmlpurifier.org/
"csrf-magic uses PHP's output buffering capabilities to dynamically rewrite forms and scripts in your document. It will also intercept POST requests and check their token (various algorithms are used; some generate nonces, some generate user-specific tokens). This means, for a traditional website with forms, you can drop csrf-magic into your application and forget about it!"