简体   繁体   English

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

[英]Securing POST data in web application

I have a web application which has basic authentication - username, password, session and stuff. 我有一个具有基本身份验证的Web应用程序-用户名,密码,会话和其他内容。 However I have a specific need to prevent users from spoofing the POST requests (even for logged in users). 但是,我特别需要防止用户欺骗POST请求(甚至对于已登录的用户)。 In my application, I am specifically validating the user's session before accepting the POST data (taking care of XSS and stuff also). 在我的应用程序中,我专门在接受POST数据之前验证用户的会话(还要注意XSS和其他内容)。

Like: 喜欢:

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

else {
   // ...
}

I am storing the sessions IDs in the database. 我将会话ID存储在数据库中。 Is there anything else I should be aware of to prevent bogus POST requests or is this sufficient? 为了防止假POST请求,我还有其他注意事项吗?

I am specifically validating the user's session before accepting the POST 我专门在接受POST之前验证用户的会话

If you mean what is normally meant by 'session': a persistent token stored in a cookie that identifies the user and associated session data, then no, that's not enough. 如果您的意思通常是“会话”,即存储在cookie中的持久性令牌,用于标识用户和关联的会话数据,那么,这还不够。 That cookie is sent automatically by the browser even if the POST request was provoked by another (attacker) site. 该cookie由浏览器自动发送,即使POST请求是由另一个(攻击者)站点引起的。

The keyword you are looking for here is Cross-Site Request Forgery or XSRF , where an authenticated user can be made by an attacker (via scripting or other methods) to make a GET or POST request to your site. 您在此处寻找的关键字是跨站点请求伪造或XSRF ,攻击者可以在其中(通过脚本或其他方法)通过身份验证的用户向您的站点发出GET或POST请求。 Such requests are not generally distinguishable from legitimate requests. 此类请求通常无法与合法请求区分开。 (Some people try to do so though checking the HTTP referrer data, but this is unreliable.) (有些人试图通过检查HTTP引荐来源网址数据来做到这一点,但这是不可靠的。)

These attacks are not quite as immediately damaging as server-side (SQL, command) or client-side (HTML, JavaScript) injections, but they are more common than both: few web programmers both to include the proper countermeasures, unfortunately. 这些攻击不会像服务器端(SQL,命令)或客户端(HTML,JavaScript)注入那样立即造成破坏,但是它们比这两种注入更为普遍:不幸的是,很少有Web程序员都包含适当的对策。 Until they get their sites compromised by an XSRF hole anyway. 直到他们的站点被XSRF漏洞破坏为止。

There are various way to defend against XSRF, but the only really effective approach is to include in each submittable form a secret value that the third-party attacker won't know. 防御XSRF的方法多种多样,但唯一真正有效的方法是在每个可提交的表单中包含第三方攻击者不知道的秘密值。 This is often known as a post key, as mentioned by Eimantas. 正如Eimantas所提到的,这通常被称为后置密钥。

There are various ways to generate such secret information. 有多种生成此类秘密信息的方法。 A simple approach is to add a randomly-generated code to each user's account details, then put that in a hidden field in the form and check for its presence in the submission. 一种简单的方法是将随机生成的代码添加到每个用户的帐户详细信息,然后将其放在表单的隐藏字段中,并检查其是否存在于提交中。 eg in PHP: 例如在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

An attacker won't know the key for that user so can't make a link/form that contains it. 攻击者不会知道该用户的密钥,因此无法创建包含该密钥的链接/表单。

You could also use a cryptographic hash function on the user's ID with a server-secret key, rather than keeping a separate code. 您还可以通过服务器秘密密钥在用户ID上使用加密哈希函数,而不用保留单独的代码。 With a hash, you can also throw in other stuff like an expiry time so that forms have to be submitted within a certain timeframe. 使用散列,您还可以添加其他内容,例如到期时间,以便必须在特定时间范围内提交表单。 Or you can generate a one-use transaction key, which you can also use to make sure you can't submit the same form twice (for stopping double-posting). 或者,您可以生成一次性使用的交易密钥,也可以使用该交易密钥来确保不会两次提交相同的表单(用于停止重复发布)。

You could try generating post keys for each post request. 您可以尝试为每个发布请求生成发布密钥。 Sort of additional param that shows that post request is valid and was executed from a form on your page. 其他种类的参数,用于显示发布请求有效且已从页面上的表单执行。

If you are building valid POST requests in Javascript in the user's browser, there is not much you can do to prevent a determined user from submitting bogus POSTs to your server. 如果要在用户浏览器中的Javascript中构建有效的POST请求,则您无法做很多事情来阻止确定的用户向服务器提交虚假的POST。 The user has a valid session id that he can use to make a POST request. 用户具有可用于发出POST请求的有效会话ID。 He also has access to all of the code and all the other data that code has access to for building the request. 他还有权访问所有代码以及该代码有权访问以建立请求的所有其他数据。

You can't rely on browser-side code to secure your system. 您不能依靠浏览器端代码来保护系统。 The security has to be enforced at the server. 必须在服务器上强制执行安全性。 For example, all operations on objects should be authenticated and authorized. 例如,对对象的所有操作都应经过身份验证和授权。

Use a CAPTCHA image. 使用验证码图片。

The web is built on REST, which by definition is all about transferring state from one point to another. Web建立在REST之上,根据定义,REST就是将状态从一个点转移到另一个点。 Someone with enough time on their hands could craft a POST request that emulates an active session. 手上有足够时间的人可以制作一个模拟活动会话的POST请求。

Like all secure requests, CAPTCHA is validated server-side. 与所有安全请求一样,验证码也在服务器端经过验证。

In my current application I have some code which is sent to the browser and the browser then posts back and must not be able to modify it. 在我当前的应用程序中,我有一些代码发送到浏览器,然后浏览器回发,并且一定不能修改它。 What I do is to append a secret string to the value, get the SHA1 checksum of that full string, and then require the browser to send back both the value and the checksum. 我要做的是将一个秘密字符串附加到该值,获取该完整字符串的SHA1校验和,然后要求浏览器将值和校验和都发送回去。 I'm pretty sure this is how .NET does viewstate, too. 我很确定这也是.NET进行viewstate的方式。

If user session is long-lived, you are still susceptible to XSRF . 如果用户会话是长期的,那么您仍然容易受到XSRF的影响 You need to take measures against that too. 您也需要采取措施。

If you are on .NET, check out AntiForgeryToken, 如果您使用的是.NET,请查看AntiForgeryToken,

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

When accepting user input, the zero-level thing you need to do, before storing things in the database is to make sure you run the data via the mysql_real_escape_string($MyPostData) function. 接受用户输入时,在将内容存储到数据库之前,需要执行的零级操作是确保您通过mysql_real_escape_string($ MyPostData)函数运行数据。

Also, it is good for every variable/data you want to accept via POST to validate it programmatically based on its type and what you intend to do with it. 同样,对于您希望通过POST接受的每个变量/数据,根据其类型以及您打算如何使用它,以编程方式对其进行验证也是有益的。

These are two main rules for making sure there's no 'funny' business coming from the user: making sure you work with valid variables AND making sure data that gets to the database is verified and escaped properly. 这是确保没有来自用户的“滑稽”生意的两个主要规则:确保您使用有效的变量,并确保对进入数据库的数据进行了验证并正确地进行了转义。

With your model (and especially if you use integer numbers for your session IDs) an attacker can easily submit a request on behalf of another user (eg decrement your own session ID and you are already someone else provided this session ID exists). 使用您的模型(尤其是如果您使用整数作为会话ID),攻击者可以轻松地代表另一个用户提交请求(例如,减少您自己的会话ID,并且只要存在此会话ID,您就已经是其他人了)。 You need to have a unique session key/guid associated with each session ID and stored both in the DB and on the client in the cookies. 您需要具有与每个会话ID关联的唯一会话密钥/ GUID,并存储在数据库和cookie中的客户端上。 Each time your client submits a request you should read not only session ID but also the session GUID and then validate them both against your database values. 每次客户提交请求时,您不仅应读取会话ID,还应读取会话GUID,然后根据您的数据库值对它们进行验证。 In addition to that you may also want to consider some XSRF mitigation strategies. 除此之外,您可能还需要考虑一些XSRF缓解策略。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM