会话ID放置:表单隐藏字段与HTTPOnly Cookie

时间:2022-05-02 18:17:46

What are the advantages and disadvantages of placing session id in a hidden form input vs a cookie?

将会话ID放在隐藏表单输入与cookie中的优点和缺点是什么?

Is it correct to put CSRF-Tag in a hidden form input field and session id in an httpOnly cookie? Which is more secure?

将CSRF-Tag放入隐藏表单输入字段和httpOnly cookie中的会话ID是否正确?哪个更安全?

2 个解决方案

#1


I don't think that one is inherently less secure than the other. Security is generally built in layers. By asserting that choice A can be more secure than choice B, when both choices play on the same vertical, you are asserting that security stops there. This is completely false and unsubstantiated in practice.

我不认为一个人本身就不如另一个人那么安全。安全性通常是分层构建的。通过声明选择A可以比选择B更安全,当两个选项在同一垂直上播放时,您断言安全性在那里停止。这在实践中是完全错误的和未经证实的。

By passing around session ids primarily in the form of hidden form inputs you actually create more problems than you solve for yourself. Also, I disagree with the assertion that this in anyway makes you inherently protected from CSRF.

通过主要以隐藏表单输入的形式传递会话ID,实际上您创建的问题比您自己解决的问题多。此外,我不同意断言这无论如何都会让你固有地受到CSRF的保护。

When you think about what purpose a session serves (retaining state between the server and client over an otherwise stateless protocol), it doesn't actually make sense to say I will pass all of my session ids via hidden input fields. Because, for one, not every request made to your server involves the use of a form. For another, the state is lost the moment the user refreshes the page or closes their browser. This isn't pragmatic at all.

当您考虑会话服务的目的(通过其他无状态协议保留服务器和客户端之间的状态)时,说我将通过隐藏的输入字段传递所有会话ID实际上没有意义。因为,对于一个,并非每个向您的服务器发出的请求都涉及使用表单。另一方面,当用户刷新页面或关闭浏览器时,状态就会丢失。这根本不是务实的。

It is correct to place CSRF tokens in hidden inputs. It's also not incorrect to send them along to the client via HTTP headers. The CSRF token by itself isn't enough to prevent the attack. What's also needed is that the server understands how to recognize that this toke, which was supposedly uniquely generated for this client, is not reused and not tied to another session by the same user.

将CSRF令牌置于隐藏输入中是正确的。通过HTTP标头将它们发送到客户端也没有错误。 CSRF令牌本身不足以阻止攻击。还需要的是服务器理解如何识别这个为该客户端唯一生成的toke,不会被重用,也不会被同一个用户绑定到另一个会话。

Since generally a CSRF attack is based on the premise that you cannot distinguish the real user from the malicious forgery, the idea is to make the forger's job more difficult by regenerating the token for every request. Coupled with a use-only-once requirement and it doesn't actually matter anymore that the session is hijacked. So you really shouldn't try to solve this problem at the wrong level, by assuming that you can somehow solve both problems by relying on passing your session ids in hidden inputs and convincing yourself that this is more secure than storing the session id in a cookie. It's not. There should be additional layers of security to protect your sessions from session hijacking or session fixation attacks like using SSL only cookies, HSTS, and regnerating session ids (while deleting the old session files) upon re-authentication requests. Also, forcing re-authentication for user-level non-idempotent actions.

由于CSRF攻击通常基于您无法区分真实用户和恶意伪造的前提,因此通过为每个请求重新生成令牌,使得伪造者的工作更加困难。再加上只使用一次的要求,会话被劫持实际上并不重要。所以你真的不应该试图在错误的层面解决这个问题,假设你可以通过依赖于在隐藏的输入中传递你的会话ID并以某种方式解决这两个问题,并说服自己这比将会话ID存储在一个更安全曲奇饼。不是。应该有额外的安全层来保护会话免受会话劫持或会话固定攻击,例如在重新身份验证请求时使用仅SSL的Cookie,HSTS和重新注册会话ID(同时删除旧的会话文件)。此外,强制对用户级非幂等操作进行重新身份验证。

But please please don't assume that hidden input makes you inherently more secure from CSRF or Session Fixation, or any of these attacks. It doesn't!

#2


If you put Session ID in a hidden form field, that is a lot more secure, however it can hamper the user experience.

如果您将会话ID放在隐藏的表单字段中,这会更安全,但它可能会妨碍用户体验。

The reason is that is this would inherently protect you against CSRF because any cross-domain requests made to your site will mean that the browser will not automatically include the session identifier that makes CSRF attacks possible. It also neutralises session fixation attacks as there is no cookie to poison. Additionally any Login CSRF is also dead in the water.

原因是,这本身就可以保护您免受CSRF的影响,因为对您的站点发出的任何跨域请求都意味着浏览器不会自动包含使CSRF攻击成为可能的会话标识符。它还会中断会话固定攻击,因为没有cookie可以中毒。此外,任何登录CSRF也在水中死亡。

To implement this, you would have every action on your site, including navigation, to be actioned via the POST method. The GET method would be unsuitable because this would expose the session identifier in the browser history, in any proxy or server logs by default, and can also be leaked via the referer header.

要实现此目的,您可以通过POST方法对您网站上的所有操作(包括导航)进行操作。 GET方法将是不合适的,因为这将在浏览器历史记录中,默认情况下在任何代理或服务器日志中公开会话标识符,并且还可以通过referer标头泄露。

For example,

<form method="post" action="/executeAction">

  <input type="hidden" name="sessionId" value="12345678901234567890" />
  <input type="hidden" name="action" value="navigateToAccountStatus" />

</form>

Note that this will prevent use of the back button without the user re-submitting the form (which could be dangerous if the action wasn't a safe action). To guard against this, you could refresh the session identifier after each action is processed.

请注意,这将阻止在没有用户重新提交表单的情况下使用后退按钮(如果操作不是安全操作,则可能会有危险)。为了防止这种情况,您可以在处理每个操作后刷新会话标识符。

Another reason is this will protect your site against attacks such as POODLE. As there are no cookies for a Man-In-The-Middle to brute force one byte at a time from, a POODLE attack would be fruitless.

另一个原因是这将保护您的网站免受诸如POODLE之类的攻击。由于没有任何一个字符串可以让一个人在一个字节中使用一个字节,因此POODLE攻击将毫无结果。

Note that this approach is more difficult to implement, and not many web-frameworks support it as default.

请注意,此方法更难实现,并且没有多少Web框架支持默认情况。

Is it correct to put CSRF-Tag in form hidden field and Session Id in httpOnly cookie?

将CSRF-Tag放在表单隐藏字段和会话ID在httpOnly cookie中是否正确?

Yes, this is the approach most sites take. It is "secure enough" for most purposes - only very high security systems like online banking should take the form approach.

是的,这是大多数网站采用的方法。对于大多数用途来说,它“足够安全” - 只有非常高的安全系统(如网上银行)才应采用表单方式。

#1


I don't think that one is inherently less secure than the other. Security is generally built in layers. By asserting that choice A can be more secure than choice B, when both choices play on the same vertical, you are asserting that security stops there. This is completely false and unsubstantiated in practice.

我不认为一个人本身就不如另一个人那么安全。安全性通常是分层构建的。通过声明选择A可以比选择B更安全,当两个选项在同一垂直上播放时,您断言安全性在那里停止。这在实践中是完全错误的和未经证实的。

By passing around session ids primarily in the form of hidden form inputs you actually create more problems than you solve for yourself. Also, I disagree with the assertion that this in anyway makes you inherently protected from CSRF.

通过主要以隐藏表单输入的形式传递会话ID,实际上您创建的问题比您自己解决的问题多。此外,我不同意断言这无论如何都会让你固有地受到CSRF的保护。

When you think about what purpose a session serves (retaining state between the server and client over an otherwise stateless protocol), it doesn't actually make sense to say I will pass all of my session ids via hidden input fields. Because, for one, not every request made to your server involves the use of a form. For another, the state is lost the moment the user refreshes the page or closes their browser. This isn't pragmatic at all.

当您考虑会话服务的目的(通过其他无状态协议保留服务器和客户端之间的状态)时,说我将通过隐藏的输入字段传递所有会话ID实际上没有意义。因为,对于一个,并非每个向您的服务器发出的请求都涉及使用表单。另一方面,当用户刷新页面或关闭浏览器时,状态就会丢失。这根本不是务实的。

It is correct to place CSRF tokens in hidden inputs. It's also not incorrect to send them along to the client via HTTP headers. The CSRF token by itself isn't enough to prevent the attack. What's also needed is that the server understands how to recognize that this toke, which was supposedly uniquely generated for this client, is not reused and not tied to another session by the same user.

将CSRF令牌置于隐藏输入中是正确的。通过HTTP标头将它们发送到客户端也没有错误。 CSRF令牌本身不足以阻止攻击。还需要的是服务器理解如何识别这个为该客户端唯一生成的toke,不会被重用,也不会被同一个用户绑定到另一个会话。

Since generally a CSRF attack is based on the premise that you cannot distinguish the real user from the malicious forgery, the idea is to make the forger's job more difficult by regenerating the token for every request. Coupled with a use-only-once requirement and it doesn't actually matter anymore that the session is hijacked. So you really shouldn't try to solve this problem at the wrong level, by assuming that you can somehow solve both problems by relying on passing your session ids in hidden inputs and convincing yourself that this is more secure than storing the session id in a cookie. It's not. There should be additional layers of security to protect your sessions from session hijacking or session fixation attacks like using SSL only cookies, HSTS, and regnerating session ids (while deleting the old session files) upon re-authentication requests. Also, forcing re-authentication for user-level non-idempotent actions.

由于CSRF攻击通常基于您无法区分真实用户和恶意伪造的前提,因此通过为每个请求重新生成令牌,使得伪造者的工作更加困难。再加上只使用一次的要求,会话被劫持实际上并不重要。所以你真的不应该试图在错误的层面解决这个问题,假设你可以通过依赖于在隐藏的输入中传递你的会话ID并以某种方式解决这两个问题,并说服自己这比将会话ID存储在一个更安全曲奇饼。不是。应该有额外的安全层来保护会话免受会话劫持或会话固定攻击,例如在重新身份验证请求时使用仅SSL的Cookie,HSTS和重新注册会话ID(同时删除旧的会话文件)。此外,强制对用户级非幂等操作进行重新身份验证。

But please please don't assume that hidden input makes you inherently more secure from CSRF or Session Fixation, or any of these attacks. It doesn't!

#2


If you put Session ID in a hidden form field, that is a lot more secure, however it can hamper the user experience.

如果您将会话ID放在隐藏的表单字段中,这会更安全,但它可能会妨碍用户体验。

The reason is that is this would inherently protect you against CSRF because any cross-domain requests made to your site will mean that the browser will not automatically include the session identifier that makes CSRF attacks possible. It also neutralises session fixation attacks as there is no cookie to poison. Additionally any Login CSRF is also dead in the water.

原因是,这本身就可以保护您免受CSRF的影响,因为对您的站点发出的任何跨域请求都意味着浏览器不会自动包含使CSRF攻击成为可能的会话标识符。它还会中断会话固定攻击,因为没有cookie可以中毒。此外,任何登录CSRF也在水中死亡。

To implement this, you would have every action on your site, including navigation, to be actioned via the POST method. The GET method would be unsuitable because this would expose the session identifier in the browser history, in any proxy or server logs by default, and can also be leaked via the referer header.

要实现此目的,您可以通过POST方法对您网站上的所有操作(包括导航)进行操作。 GET方法将是不合适的,因为这将在浏览器历史记录中,默认情况下在任何代理或服务器日志中公开会话标识符,并且还可以通过referer标头泄露。

For example,

<form method="post" action="/executeAction">

  <input type="hidden" name="sessionId" value="12345678901234567890" />
  <input type="hidden" name="action" value="navigateToAccountStatus" />

</form>

Note that this will prevent use of the back button without the user re-submitting the form (which could be dangerous if the action wasn't a safe action). To guard against this, you could refresh the session identifier after each action is processed.

请注意,这将阻止在没有用户重新提交表单的情况下使用后退按钮(如果操作不是安全操作,则可能会有危险)。为了防止这种情况,您可以在处理每个操作后刷新会话标识符。

Another reason is this will protect your site against attacks such as POODLE. As there are no cookies for a Man-In-The-Middle to brute force one byte at a time from, a POODLE attack would be fruitless.

另一个原因是这将保护您的网站免受诸如POODLE之类的攻击。由于没有任何一个字符串可以让一个人在一个字节中使用一个字节,因此POODLE攻击将毫无结果。

Note that this approach is more difficult to implement, and not many web-frameworks support it as default.

请注意,此方法更难实现,并且没有多少Web框架支持默认情况。

Is it correct to put CSRF-Tag in form hidden field and Session Id in httpOnly cookie?

将CSRF-Tag放在表单隐藏字段和会话ID在httpOnly cookie中是否正确?

Yes, this is the approach most sites take. It is "secure enough" for most purposes - only very high security systems like online banking should take the form approach.

是的,这是大多数网站采用的方法。对于大多数用途来说,它“足够安全” - 只有非常高的安全系统(如网上银行)才应采用表单方式。