我有一个具有基本身份验证的 Web 应用程序 - 用户名、密码、 session 等。但是,我有一个特定的需要来防止用户欺骗 POST 请求(即使是登录用户)。在我的应用程序中,我在接受 POST 数据之前专门验证用户的 session (还要处理 XSS 和其他内容)。
喜欢:
if(user session exists)
{
// handle the data POSTed
}
else {
// ...
}
我将 session ID 存储在数据库中。还有什么我应该注意的,以防止虚假的 POST 请求,或者这是否足够?
最佳答案
如果您的意思是“ session ”通常的含义:存储在 cookie 中的持久 token ,用于标识用户和关联的 session 数据,那么不,这还不够。即使 POST 请求是由另一个(攻击者)站点引发的,该 cookie 也会由浏览器自动发送。
您在此处查找的关键字是 Cross-Site Request Forgery 或 XSRF ,其中经过身份验证的用户可以由攻击者(通过脚本或其他方法)向您的站点发出 GET 或 POST 请求。此类请求通常无法与合法请求区分开来。 (有些人试图通过检查 HTTP 引用数据来这样做,但这是不可靠的。)
这些攻击不像服务器端(SQL、命令)或客户端(HTML、JavaScript)注入(inject)那样立即造成破坏,但它们比两者都更常见:不幸的是,很少有 Web 程序员同时包含适当的对策。直到他们的网站被 XSRF 漏洞攻破为止。
有多种方法可以防御 XSRF,但唯一真正有效的方法是在每个可提交表单中包含第三方攻击者不知道的 secret 值。正如 Eimantas 所提到的,这通常被称为 post key。
有多种方式来生成这样的 secret 信息。一种简单的方法是将随机生成的代码添加到每个用户的帐户详细信息中,然后将其放在表单中的隐藏字段中并检查其在提交中是否存在。例如在 PHP 中:
<form method="post" action="delete.php"><div>
<input type="hidden" name="key" value="<?php echo(htmlspecialchars($user['key'])); ?>"/>
<input type="submit" value="Delete" />
</div></form>
if ($_POST['key']!=$user['key'])
// error
攻击者不会知道该用户的 key ,因此无法创建包含它的链接/表单。
您还可以使用服务器 key 对用户 ID 使用加密散列函数,而不是保留单独的代码。使用散列,您还可以添加其他内容,例如到期时间,以便必须在特定时间范围内提交表单。或者您可以生成一次性交易 key ,您也可以使用它来确保您不能两次提交相同的表单(用于停止重复发布)。
关于security - 在 Web 应用程序中保护 POST 数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1417719/