会话 ID 不够随机 - ASP.NET
更新
我们最终与 Acunetix 团队的一些程序员进行了会面,他们意识到他们的代码中可能存在一些错误,导致扫描中显示的问题比实际问题更大或许。普遍的共识是忽略扫描结果并使用开箱即用的 ASP.NET 会话 ID 生成,因为它对于我们的站点来说应该足够安全。
@Vasile Bujac,因为您的答案是唯一的,并且提到使用 ASP.NET 标准解决方案,所以我将其作为答案,但感谢大家的帮助。
我们在工作中使用 Acunetix 的 Retina 扫描仪对我们的应用程序进行安全扫描。它告诉我们,我们的会话 ID 不够随机且太可预测。我不太确定 ASP.NET 默认情况下如何生成会话 ID(我认为它是 GUID?),但我继续实现了扩展 SessionIDManager 类并重写 CreateSessionID 和 Validate 方法以使用 Guid 的方法如 这篇 MSDN 文章。
虽然这使得它更加随机,但根据 Acunetix 的说法,它仍然没有产生“期望的”效果。我什至将 regenerateExpiredSessionId="true"
属性添加到 web.config 中,但这没有任何效果。我有一种感觉,我可能需要刻意调用Session.Abandon()
来真正清除会话并获得新的ID。问题是我必须在用户登录之前调用它,因为这是了解用户正在开始新会话的唯一防故障方法。因此,在使用 Abandon
方法加载下一页之前,我无法在会话中设置任何内容,这意味着中间页面不是很理想,但可以解决问题。
有没有人经历过这种情况或成功实施了修复?
另外,仅供参考,我们不使用成员资格/表单身份验证,我们只是在有人登录时创建一个新的自定义用户类并将其保存在会话中以供以后使用。
来自 Acunetix 的报告:
描述:表现较低的会话令牌熵(“随机性”)通常容易受到预测攻击。不安全的令牌可能是由于伪随机数生成器、基于时间的值、静态值或基于用户属性(用户名或用户 ID)的值不足造成的。这意味着攻击者在短时间内监视应用程序并收集其创建的会话令牌后,将能够猜测有效的会话令牌。如果攻击者确定了另一个用户的有效会话令牌,则可以查看、修改或删除任意用户的数据,而无需猜测受害者的用户名或密码。因此,推断有效会话令牌的能力使攻击者能够绕过登录页面并避免暴力破解帐户的需要。此外,即使受害者当前未登录应用程序,静态令牌也可以使攻击者能够瞄准用户。这增加了攻击者可以瞄准的受害者群体。
会话令牌应该使用强大的随机数生成器创建并从大量数字中收集。例如,如果操作系统的 rand() 函数可以生成统计上均匀分布的 32 位值,那么它通常就足够了。较差的会话令牌是增量的、依赖于用户的帐户 ID、仅使用时间戳或具有其他高度确定性的信息。保护会话令牌安全的其他方法包括始终通过 SSL 传输它们、在一段时间后自动使令牌过期以及在用户注销应用程序时显式使令牌过期。
建议:如果会话值表现出很强的随机性,但是从一小部分值中选择的,那么攻击者就有更好的机会简单地猜测有效令牌。可以通过实施多种补充技术来改进 Web 应用程序的会话管理:
- 确保 Token 值的大小至少为 32 位,特别是对于具有大量并发用户和大量每日页面请求的应用程序。
- 熵源(随机值)的位大小比实际会话令牌的位大小更重要。例如,MD5 哈希会生成 128 位值。然而,增量值、时间戳或 8 位随机数的 MD5 散列都是不安全的,因为可以轻松预测随机值的来源。因此,128 位大小并不代表会话令牌的准确度量。熵源的最小大小为 32 位,但对于每小时超过 10,000 个并发用户的站点可能需要更大的池(48 或 64 位)。
- 在大多数情况下,应用程序生成的令牌(例如ASP.NET_SessionId、ASPSESSIONID、JSPSESSIONID、PHPSESSIONID)提供足够大的随机值以防止会话预测攻击。应用程序应该使用这些会话管理算法,除非自定义会话机制已经过彻底的审查和测试。
- 使用服务器端对象跟踪与会话令牌关联的用户属性,以防止用户模拟攻击。如果应用程序没有严格地将用户的会话令牌与该用户的配置文件信息相关联,则攻击者可能能够通过操纵客户端值来查看任意信息。例如,如果应用程序设置了强会话令牌,但基于“UserId”cookie 执行 SQL 查询,则攻击者只需修改“UserId”cookie 即可冒充其他人。如果应用程序将“UserId”值与服务器端会话对象相关联,那么应用程序将更加安全,因为攻击者将无法修改该值。
- 当用户注销应用程序或在预定的不活动时间后,会话令牌将过期。我们建议对会话令牌使用 20 分钟的超时,尽管这很大程度上取决于应用程序的类型和预期的使用情况。
UPDATE
We eventually had a meeting with some programmers on the Acunetix team and they realized there may be a few bugs in their code that are causing this to be displayed in the scan as more of an issue than it actually may be. The general consensus was to ignore the scan results and use the out-of-the-box ASP.NET Session ID generation as it should be secure enough for our site.
@Vasile Bujac since your answer was the only one and mentioned using the ASP.NET standard solution I took that as the answer, but thanks everyone for your help.
We use Acunetix's Retina scanner at work to do security scans on our applications. It's telling us that our session ID's are not random enough and too predictable. I'm not exactly sure how ASP.NET generates the session ID by default (I thought it was GUID anyways?), but I went ahead and implemented the method of extending the SessionIDManager class and overriding the CreateSessionID and Validate methods to use a Guid as explained in this MSDN article.
While this makes it slightly more random, it is still not producing the "desired" effect according to Acunetix. I even added the regenerateExpiredSessionId="true"
property to the web.config and that had no effect. I have a feeling that I may need to deliberately call Session.Abandon()
to truly clear the session and get a new ID. Problem is then I have to call it right before a user logs in since it's the only fail-proof way to know the user is starting a new session. So I couldn't set anything in session until the next page is loaded with the way the Abandon
method works, and that would mean an in-between page which isn't very ideal but would do the trick.
Has anyone ever experienced this or successfully implemented a fix?
Also, just an FYI, we don't use membership/forms authentication, we just create a new custom user class when someone logs in and save that in session for later use.
Report from Acunetix:
Description: Session tokens that exhibit low entropy ("randomness") are often susceptible to prediction attacks. Insecure tokens can be due to inadequate pseudo-random number generator, time-based values, static values, or values based on user attributes (username or user ID). This means that an attacker would be able to guess a valid session token after monitoring the application for a short period of time and gathering the session tokens it creates. If the attacker determines a valid session token for another user, then it may be possible to view, modify, or delete arbitrary users' data without having to guess the victim's username or password. Consequently, the ability to deduce valid session tokens enables the attacker to bypass login pages and obviate the need to brute force accounts. Additionally, static tokens can enable the attacker to target users even if the victim is not currently logged into the application. This increases the pool of victims which the attacker can target.
Session tokens should be created with a strong random number generator and gathered from a large pool of numbers. For example, an operating system's rand() function can usually be sufficient if it can produce 32-bit values that are a statistically uniform distribution. Poor session tokens are incremental, rely on the user's account ID, only use time stamps, or have other highly deterministic information. Other methods of protecting a session token's security are to always transmit them over SSL, automatically expire the token after a certain period of time, and explicitly expiring the token whenever a user logs out of the application.
Recommendations: If the session values exhibit strong randomness, but are chosen from a small pool of values, then the attacker has a better chance of simply guessing a valid token. A web application's session management can be improved by implementing several complementary techniques:
- Make sure that the Token values are at least 32 bits in size, especially for applications with large numbers of concurrent users and high amounts of daily page requests.
- The bit size of the source of the entropy (random values) is more important than the bit size of the actual session token. For example, an MD5 hash produces a 128 bit value. However, the MD5 hash of incremental values, a timestamp, or 8-bit random numbers are each insecure because the source of the random values can be easily predicted. Consequently, the 128 bit size does not represent an accurate measure of the session token. The minimum size of the entropy source is 32 bits, although larger pools (48 or 64 bits) may be necessary for sites with over 10,000 concurrent users per hour.
- In most cases, application-generated tokens (e.g. ASP.NET_SessionId, ASPSESSIONID, JSPSESSIONID, PHPSESSIONID) provide sufficiently large random values to prevent session prediction attacks. The application should use these session management alogorithms unless a custom session mechanism has been thoroughly reviewed and tested.
- Track user attributes associated with the session token with server-side objects to prevent user impersonation attacks. If the application does not strictly associate a user's session token with that user's profile information, then an attacker may be able to view arbitrary information by manipulating client-side values. For example, if the application sets a strong session token, but performs SQL queries based on a "UserId" cookie, then an attacker only needs to modify the "UserId" cookie to impersonate someone else. The application would be more secure if it associated the "UserId" value with the server-side session object because the attacker would not be able to modify the value.
- Expire session tokens when the user logs out of the application or after a predetermined period of inactivity. We recommend using a 20 minute timeout for a session token, although this largely depends on the type of application and the expected usage.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我记得,ASP.NET 会话 ID 生成器针对会话预测提供了良好的保护。会话 ID 有 24 个字符,使用 [az] 字符和 [0-5] 数字(总共 32 个可能的字符,即 2^5),总共有 2^(5*24) = 2^120 个可能的值。但是,您可以实现 SessionIDManager 来附加一些信息(例如用户主机地址、用户代理、使用 HMAC 算法的验证令牌)以获得更好的保护 - 这样来自不同 IP 地址或不同浏览器的会话 id 就不会通过验证。如果您实施了表单身份验证,则不需要这样做,因为身份验证票证已经提供了此类保护。
如果您想要更好的随机会话 ID,您可以在 SessionIDManager 中使用 RandomNumberGenerator(例如 RNGCryptoServiceProvider)并填充一堆字节(例如 32,即 256 位),然后使用 Base64 对它们进行编码
但是, 此文章 说您的会话 ID 的最大长度为 80,因此您也必须重写 Validate 方法才能使其正常工作。
As I remember, ASP.NET session id generator gives good protection against session prediction. The session id has 24 characters using [a-z] chars and [0-5] digits (total of 32 possible chars which is 2^5) which gives a total of 2^(5*24) = 2^120 possible values. However you can implement a SessionIDManager to append some information (like user hostaddress, user-agent, a validation token using a HMAC algorithm) for even better protection - so that a session id comming from a different IP Address or different browser wouldn't pass the validation. If you have forms authentication implemented, this is not necessary since the authentication ticket already provides these kinds of protection.
If you want a better random session id you can use a RandomNumberGenerator such as RNGCryptoServiceProvider in your SessionIDManager and fill a bunch of bytes (say 32 which is 256 bits), then encode them using Base64
However, this article says that the max length of your session id is 80, so you must override the Validate method also in order for it to work.