3

我有一个具有基本身份验证的 Web 应用程序 - 用户名、密码、会话和东西。但是,我特别需要防止用户欺骗 POST 请求(即使对于已登录的用户)。在我的应用程序中,我在接受 POST 数据之前专门验证用户的会话(还要处理 XSS 和其他东西)。

喜欢:

if(user session exists)
{
    // handle the data POSTed
}

else {
   // ...
}

我将会话 ID 存储在数据库中。还有什么我应该注意的以防止虚假的 POST 请求还是足够了?

4

8 回答 8

3

我在接受 POST 之前专门验证用户的会话

如果您的意思是“会话”的通常含义:存储在 cookie 中的持久令牌,用于标识用户和关联的会话数据,那么不,这还不够。即使 POST 请求是由另一个(攻击者)站点引发的,该 cookie 也会由浏览器自动发送。

您在此处查找的关键字是 Cross-Site Request Forgery 或XSRF,攻击者(通过脚本或其他方法)可以使经过身份验证的用户向您的站点发出 GET 或 POST 请求。此类请求通常无法与合法请求区分开来。(有些人尝试通过检查 HTTP 引用数据来这样做,但这是不可靠的。)

这些攻击不像服务器端(SQL、命令)或客户端(HTML、JavaScript)注入那样具有直接破坏性,但它们比两者都更常见:不幸的是,很少有 Web 程序员同时包含适当的对策。直到他们的网站受到 XSRF 漏洞的影响。

有多种方法可以防御 XSRF,但唯一真正有效的方法是在每个可提交的表单中包含一个第三方攻击者不会知道的秘密值。正如 Eimantas 所提到的,这通常被称为 post 键。

有多种方法可以生成这样的秘密信息。一种简单的方法是将随机生成的代码添加到每个用户的帐户详细信息中,然后将其放入表单的隐藏字段中并检查其是否存在于提交中。例如在 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

攻击者不知道该用户的密钥,因此无法创建包含它的链接/表单。

您还可以使用服务器密钥对用户 ID 使用加密哈希函数,而不是保留单独的代码。使用哈希,您还可以输入其他内容,例如到期时间,以便必须在特定时间范围内提交表单。或者您可以生成一次性交易密钥,您也可以使用它来确保您不能两次提交相同的表单(用于停止重复发布)。

于 2009-09-13T15:12:36.073 回答
2

您可以尝试为每个发布请求生成发布密钥。显示发布请求有效并且从您页面上的表单执行的附加参数的排序。

于 2009-09-13T13:19:09.500 回答
1

如果您在用户浏览器中使用 Javascript 构建有效的 POST 请求,则您无法阻止确定的用户向您的服务器提交虚假 POST。用户具有可用于发出 POST 请求的有效会话 ID。他还可以访问所有代码以及代码可以访问以构建请求的所有其他数据。

您不能依靠浏览器端代码来保护您的系统。必须在服务器上强制执行安全性。例如,对对象的所有操作都应该经过身份验证和授权。

于 2009-09-13T13:22:52.477 回答
1

使用验证码图像。

Web 是建立在 REST 之上的,根据定义,REST 就是将状态从一个点转移到另一个点。有足够时间的人可以制作模拟活动会话的 POST 请求。

与所有安全请求一样,CAPTCHA 在服务器端进行验证。

于 2009-09-13T13:48:14.150 回答
0

在我当前的应用程序中,我有一些代码发送到浏览器,然后浏览器发回并且不能修改它。我所做的是将一个秘密字符串附加到该值,获取该完整字符串的 SHA1 校验和,然后要求浏览器发送回该值和校验和。我很确定这也是.NET 执行视图状态的方式。

于 2009-09-13T13:34:57.360 回答
0

如果用户会话是长期存在的,您仍然容易受到XSRF的影响。你也需要采取措施。

如果您使用的是 .NET,请查看 AntiForgeryToken,

http://msdn.microsoft.com/en-us/library/dd492767.aspx

于 2009-09-13T13:41:37.640 回答
0

接受用户输入时,在将内容存储到数据库之前,您需要做的零级事情是确保通过 mysql_real_escape_string($MyPostData) 函数运行数据。

此外,您希望通过 POST 接受的每个变量/数据都可以根据其类型和您打算对其执行的操作以编程方式对其进行验证。

这是确保没有来自用户的“有趣”业务的两个主要规则:确保使用有效变量并确保正确验证和转义进入数据库的数据。

于 2009-09-13T13:46:40.630 回答
0

使用您的模型(特别是如果您使用整数作为会话 ID),攻击者可以轻松地代表另一个用户提交请求(例如,减少您自己的会话 ID,并且您已经是其他人,前提是该会话 ID 存在)。您需要有一个与每个会话 ID 相关联的唯一会话密钥/guid,并存储在数据库和客户端的 cookie 中。每次您的客户提交请求时,您不仅应该阅读会话 ID,还应该阅读会话 GUID,然后根据您的数据库值验证它们。除此之外,您可能还需要考虑一些 XSRF 缓解策略。

于 2009-09-13T13:52:34.900 回答