保护Web应用程序中的POST数据

时间:2009-09-13 13:14:44

标签: security web-applications http-post

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

像:

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

else {
   // ...
}

我将会话ID存储在数据库中。还有什么我应该知道的,以防止伪造POST请求或这是否足够?

8 个答案:

答案 0 :(得分:3)

  

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

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

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

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

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

有多种方法可以生成这样的秘密信息。一种简单的方法是将随机生成的代码添加到每个用户的帐户详细信息中,然后将其放在表单中的隐藏字段中,并检查其在提交中的存在。例如在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进行加密哈希函数,而不是保留单独的代码。使用哈希,您还可以输入其他内容,例如到期时间,以便必须在特定时间范围内提交表单。或者您可以生成一次性交易密钥,您也可以使用该密钥确保您不能两次提交相同的表单(用于停止双重发布)。

答案 1 :(得分:2)

您可以尝试为每个帖子请求生成帖子密钥。一系列额外的参数,表明帖子请求有效并且是从页面上的表单执行的。

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

使用CAPTCHA图片。

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

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

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

答案 6 :(得分:0)

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

此外,您希望通过POST接受的每个变量/数据都可以根据其类型以及您打算使用它来以编程方式验证它。

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

答案 7 :(得分:0)

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