如何在 GAE 应用中最好地防止 CSRF 攻击?
那么,防止 GAE 应用程序遭受 XSRF 攻击的最佳方法是什么? 想象一下以下情况:
- 任何人都可以看到用户的公共对象,并且请求中使用 db.Model id 来确定要显示哪个对象。 恶意用户现在拥有该 ID。
- 恶意用户创建自己的对象并签出删除表单。 他们现在知道如何删除具有特定 ID 的对象。
- 恶意用户让无辜用户提交对该用户对象的删除请求。
我可以添加哪些步骤来防止#3? 请注意,当我说 ID 时,我使用的是密钥的实际 ID 部分。 我的一个想法是在删除请求中使用完整的键值,但这会阻止恶意用户弄清楚这一点吗? 据我所知,密钥是模型类类型、应用程序 id 和对象实例 id 的某种组合,因此如果他们愿意,他们可能可以从 id 派生密钥。
还有其他想法吗? Jeff 写了一篇关于此的文章,并提出了几种方法 - 隐藏表单值这会在每次请求时发生变化,并通过 js 将 cookie 值写入表单。 我不想排除非 javascript 用户,因此 cookie 解决方案不好 - 对于隐藏的表单值,我必须对显示可删除对象的每个请求进行数据存储写入 - 对于可扩展的情况来说这不是理想的情况应用程序!
还有其他想法吗?
So, what is the best way to prevent an XSRF attack for a GAE application? Imagine the following:
- Anyone can see a user's public object, and the db.Model id is used in the request to figure out which object to show. Malicious user now has the id.
- Malicious user creates their own object and checks out the delete form. They now know how to delete an object with a certain id.
- Malicious user gets innocent user to submit a delete request for that user's object.
What steps can I add to prevent #3? Note that when I say ID, I am using the actual ID part of the key. One idea I had was to use the full key value in delete requests, but would that prevent a malicious user from being able to figure this out? As far as I know, the key is some combination of the model class type, the app id, and the object instance id, so they could probably derive the key from the id if they wanted to.
Any other ideas? Jeff wrote a post about this, and suggested a couple methods - a hidden form value that would change on each request, and a cookie value written via js to the form. I won't want to exclude non-javascript users, so the cookie solution is no good - for the hidden form value, I would have to do a datastore write on every request that displayed a deletable object - not an ideal situation for a scalable app!
Any other ideas out there?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当您生成允许用户删除对象的页面时,生成一个随机令牌并将其包含在隐藏表单字段中。 还可以使用该值设置仅 HTTP 的 cookie。 当您收到删除请求时,请检查表单中的随机令牌与 cookie 中的值是否匹配。
您的随机令牌不应该只是一个随机数。 您应该对随机数和用户身份的组合进行加密,以使攻击者难以伪造自己的令牌。 您还应该对表单中存储的值和 cookie 中存储的值使用不同的加密密钥,因此,如果其中一个令牌确实泄漏,攻击者仍然很难伪造另一个令牌。
此方法通过表单中是否存在安全令牌来验证删除请求是否源自您的表单; 并且不需要写入数据存储。
此方法仍然容易受到跨站点脚本攻击,攻击者可以从表单中检索隐藏值或提交表单,因此请彻底测试您的站点是否存在跨站点脚本漏洞。 这种方法也容易受到“clickjacking”攻击。
When you generate the page that lets the user delete an object, generate a random token and include it in a hidden form field. Also set a HTTP-only cookie with that value. When you receive a delete request, check that the random token from the form and the value from the cookie match.
Your random token shouldn't just be a random number. You should encrypt the combination of a random number and the user's identity, to make it difficult for attackers to forge their own tokens. You should also use different encryption keys for the value stored in the form and the value stored in the cookie, so if one of the tokens does leak, it is still difficult for an attacker to forge the other token.
This approach verifies that the delete request originates from your form, by the presence of the security token in the form; and doesn't require writing to the datastore.
This approach is still vulnerable to cross-site scripting attacks, where an attacker could retrieve the hidden value from the form or submit the form, so thoroughly test your site for cross-site scripting vulnerabilities. This approach is also vulnerable to "clickjacking" attacks.
简单:检查引用者。 (故意)不可能使用 Javascript、HTML 表单等来设置它。如果它是空白的(某些代理和浏览器会删除引用)或来自您自己的站点 - 或者更具体地说来自预期来源 - 允许它。 否则,拒绝并记录它。
编辑:Jeff 写了一篇后续文章,其中提供了几种方法防止CSRF攻击。
Simple: Check the referer. It's (deliberately) impossible to set this using Javascript, HTML forms, etc. If it's blank (some proxies and browsers strip referers) or from your own site - or more specifically from the expected source - allow it. Otherwise, deny it and log it.
Edit: Jeff wrote a followup article with a couple of ways to prevent CSRF attacks.
在显示表单的服务器响应中,创建一个神奇的哈希值(基于客户端 ip + 日期/时间 + 随机盐,等等)。 将其放入 cookie 中并存储在服务器上的某个位置。 在提交操作处理期间,根据数据库条目检查 cookie 哈希值。
如果没有这样的哈希值或者不同,则拒绝提交。
成功提交后,您可以删除哈希条目,将其状态更改为已提交 - 无论您适合什么。
这种方法在很多情况下应该可以保护你,但肯定仍然不是 100% 万无一失。
搜索有关 CSRF 的文章,也许您会找到关于 Stack Overflow 问题的一些很好的答案。 ;)
不要进行任何引荐来源网址检查或客户端 IP 验证 - 这太容易出错(引荐来源网址信息可能会被用户代理、代理或用户的首选项清除),并且客户端的 IP 可能会在表单创建和提交之间发生变化 -不要因为动态IP地址分配而惩罚用户。
In server's response displaying the form create a magic hash (based on client ip + date/time + random salt, whatever). Put it into a cookie and store somewhere on the server. During submit action handling check the cookie hash against the database entry.
If there's no such hash or it's different, reject the submission.
After successful submit you can remove the hash entry, change it's state to submitted - whatever suits you.
That method should protect you in many cases, but surely is still not 100% bulletproof.
Do a search for articles on CSRF, maybe you'll find some good answers on this Stack Overflow thing. ;)
Don't do any referrer checks or client ip validations - it's too error-prone (the referrer information might be cleared by the user agent, a proxy or by user's preferences) and client's IP might change between the form creation and submission - don't punish the user for dynamic IP address allocation.