会话 ID 不够随机 - ASP.NET

Posted

技术标签:

【中文标题】会话 ID 不够随机 - ASP.NET【英文标题】:Session ID not random enough - ASP.NET 【发布时间】:2011-10-17 16:06:47 【问题描述】:

更新

我们最终与 Acunetix 团队的一些程序员进行了一次会议,他们意识到他们的代码中可能存在一些错误,这些错误导致扫描中显示的问题比实际问题更大。普遍的共识是忽略扫描结果并使用开箱即用的 ASP.NET 会话 ID 生成,因为它应该对我们的站点足够安全。

@Vasile Bujac 因为您的答案是唯一的,并且提到使用 ASP.NET 标准解决方案,所以我将其作为答案,但感谢大家的帮助。


我们在工作中使用 Acunetix 的 Retina 扫描仪对我们的应用程序进行安全扫描。它告诉我们,我们的会话 ID 不够随机且过于可预测。我不确定 ASP.NET 默认是如何生成会话 ID(我认为它还是 GUID?),但我继续实现了扩展 SessionIDManager 类并覆盖 CreateSessionID 和 Validate 方法以使用 Guid 的方法如this MSDN article 中所述。

虽然这使它稍微随机一些,但它仍然没有产生根据 Acunetix 的“所需”效果。我什至在 web.config 中添加了 regenerateExpiredSessionId="true" 属性,但没有任何效果。我有一种感觉,我可能需要特意拨打Session.Abandon() 才能真正清除会话并获得新ID。问题是我必须在用户登录之前立即调用它,因为这是知道用户正在开始新会话的唯一防故障方法。因此,在以Abandon 方法的工作方式加载下一页之前,我无法在会话中设置任何内容,这意味着中间页面不是很理想,但可以解决问题。

有没有人经历过这种情况或成功实施过修复?

另外,仅供参考,我们不使用会员/表单身份验证,我们只是在有人登录时创建一个新的自定义用户类并将其保存在会话中以供以后使用。


来自 Acunetix 的报告:

CWE-330 CAPEC-59 OWASP2007-A7

描述: 表现出低熵(“随机性”)的会话令牌通常容易受到预测攻击。不安全的令牌可能是由于伪随机数生成器、基于时间的值、静态值或基于用户属性(用户名或用户 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 分钟超时,但这在很大程度上取决于应用程序的类型和预期的使用情况。

【问题讨论】:

他们认为会话 ID 的哪个方面存在问题?你不是用它来授权的,是吗? 我刚刚将来自 acunetix 的报告添加到帖子中。不用于授权。会话 ID 的 cookie 值(“ASP.NET_SessionId”cookie)的随机性存在问题。 您是否尝试过使用 fiddler 或 firebug 查看您的 ASP.NET_SessionId cookie 值?由 ASP.NET 作为会话 id 生成的令牌远大于您的工具推荐的 32 位 Session.Abandon() 仅适用于 INPROC 【参考方案1】:

我记得,ASP.NET 会话 ID 生成器可以很好地防止会话预测。会话 id 有 24 个字符,使用 [a-z] 字符和 [0-5] 数字(总共 32 个可能的字符,即 2^5),总共有 2^(5*24) = 2^120 个可能的值。但是,您可以实现 SessionIDManager 来附加一些信息(如用户主机地址、用户代理、使用 HMAC 算法的验证令牌)以获得更好的保护 - 这样来自不同 IP 地址或不同浏览器的会话 ID 就不会通过验证。如果您实施了表单身份验证,则不需要这样做,因为身份验证票证已经提供了这些类型的保护。

如果您想要一个更好的随机会话 id,您可以在 SessionIDManager 中使用 RandomNumberGenerator,例如 RNGCryptoServiceProvider 并填充一堆字节(比如 32,即 256 位),然后使用 Base64 对其进行编码

byte[] random = new byte[100];
//RNGCryptoServiceProvider is an implementation of a random number generator.
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(random); // The array is now filled with cryptographically strong random bytes.
return Convert.ToBase64String(random) 

但是,this article 表示会话 ID 的最大长度为 80,因此您还必须重写 Validate 方法才能使其正常工作。

【讨论】:

我们没有在这个应用程序上使用表单身份验证,但我们已经使用表单身份验证在不同的应用程序上运行扫描并遇到同样的问题。 您的报告还说 ASP.NET SessionId 通常是随机的并且足够大 - 它说它必须至少有 32 位,并且 ASP.NET 中的 Session Id 比这大得多。您是否尝试过查看 cookie 的值是多少? (在 Mozilla 中使用 fiddler 或 firebug) 根据 OP 中的链接文章,听起来这正是出现此警告的原因 - 它们触发了 32 个可能的字符,因为它们太窄,而没有查看长度或生成方法。 我认为 2^120 个值还不够 我的意思是,他们正在查看单个字符内的值范围,而不是 Id 的整体范围。

以上是关于会话 ID 不够随机 - ASP.NET的主要内容,如果未能解决你的问题,请参考以下文章

将会话ID从Selenium传递到Python请求

会话 ID 轮换是不是增强了安全性?

面临问题在我的数据库中插入会话 ID

创建一个具有唯一 ID 1 小时的会话 - PHP

当所有检索值在laravel中具有相同的会话键时,如何检查会话数组是不是具有唯一的ID

php Session配置