我刚刚在网上阅读了有关 ASP.NET 中新发现的安全漏洞的信息。 You can read the details here.
问题在于 ASP.NET 实现 AES 加密算法以保护这些应用程序在用户会话期间存储信息而生成的 cookie 的完整性的方式。
这有点模糊,但这里有一个更可怕的部分:
攻击的第一阶段需要几千个请求,但是一旦成功并且攻击者获得了密钥,它就完全是隐秘的。所需的密码知识非常基础。
总而言之,我对安全/密码学主题不够熟悉,不知道这是否真的那么严重。
那么,所有 ASP.NET 开发人员是否应该害怕这种可以在几秒钟内拥有任何 ASP.NET 网站的技术呢?
这个问题对普通的 ASP.NET 开发人员有何影响?它对我们有影响吗?在现实生活中,这个漏洞的后果是什么?最后:是否有一些解决方法可以防止此漏洞?
感谢您的回答!
编辑:让我总结一下我得到的回复
所以,这基本上是一种“填充预言”类型的攻击。 @Sri 很好地解释了这种攻击的含义。 Here is a shocking video about the issue!
关于这个漏洞的严重性:是的,确实很严重。它让攻击者能够了解应用程序的机器密钥。因此,他可以做一些非常不受欢迎的事情。
在拥有应用程序的机器密钥后,攻击者可以解密身份验证 cookie。
更糟糕的是,他可以使用任何用户的名称生成身份验证 cookie。因此,他可以在网站上以任何人的身份出现。该应用程序无法区分您还是为自己生成了带有您的姓名的身份验证 cookie 的黑客。
它还允许他解密(并生成)会话 cookie,尽管这不像前一个那样危险。
没那么严重:他可以解密页面的加密 ViewState。 (如果您使用 ViewState 来存储机密数据,则无论如何都不应该这样做!)
非常出乎意料:通过机器密钥的知识,攻击者可以从您的 Web 应用程序中下载任意文件,甚至是那些通常无法下载的文件! (包括Web.Config等)
这是我得到的一堆好的做法,它们并不能解决问题,但有助于提高 Web 应用程序的一般安全性。
您可以使用受保护的配置加密敏感数据
仅使用 HTTP cookie
防止 DoS 攻击
现在,让我们专注于这个问题。
Scott Guthrie 在他的博客上发表了一篇关于它的文章
ScottGu 关于该漏洞的常见问题解答博客文章
ScottGu 关于漏洞的更新
微软有一个关于它的安全建议
了解漏洞
有关漏洞的其他信息
解决方案
启用 customErrors 并创建一个将所有错误重定向到的错误页面。是的,甚至是 404。 (ScottGu 说区分 404 和 500 对于这种攻击至关重要。)另外,在 Application_Error 或 Error.aspx 中放入一些随机延迟的代码。 (生成一个随机数,并使用 Thread.Sleep 休眠那么久。)这将使攻击者无法确定您的服务器上究竟发生了什么。
有些人建议切换回 3DES。理论上,如果不使用 AES,就不会遇到 AES 实现中的安全漏洞。事实证明,这根本不推荐。
其他一些想法
似乎不是每个人都认为解决方法足够好。
感谢所有回答我问题的人。我不仅学到了很多关于这个问题的知识,而且学到了很多关于网络安全的知识。我将@Mikael 的答案标记为已接受,但其他答案也非常有用。
我该怎么做才能保护自己?
[2010-09-29更新]
KB Article with reference to the fix
ScottGu 有下载链接
[2010-09-25更新]
在我们等待修复的同时,昨天 ScottGu postet an update 介绍了如何添加额外的步骤来使用自定义 URLScan 规则保护您的网站。
此外,在错误页面中添加随机时间休眠,以防止攻击者从 timing the responses 获取添加的攻击信息。
在 web.config
<configuration>
<location allowOverride="false">
<system.web>
<customErrors mode="On" defaultRedirect="~/error.html" />
</system.web>
</location>
</configuration>
这会将任何错误重定向到返回 200 状态代码的自定义页面。这样,攻击者就无法查看错误代码或错误信息以获取进一步攻击所需的信息。
设置 customErrors mode="RemoteOnly"
也是安全的,因为这将重定向“真实”客户端。只有从 localhost 浏览才会显示内部 .Net 错误。
重要的部分是确保所有错误都配置为返回相同的错误页面。这要求您明确设置 <customErrors>
部分的 defaultRedirect
属性,并确保未设置每个状态代码。
有什么风险?
如果攻击者设法使用上述漏洞,他/她可以从您的 Web 应用程序中下载内部文件。通常 web.config 是一个目标,可能包含敏感信息,如数据库连接字符串中的登录信息,甚至链接到您不希望有人掌握的自动 sql-express 数据库。但是,如果您遵循最佳做法,您可以使用 Protected Configuration 来加密 web.config 中的所有敏感数据。
参考文献链接
在 http://www.microsoft.com/technet/security/advisory/2416728.mspx 阅读 Microsoft 关于该漏洞的官方评论。特别是有关此问题的实施细节的“解决方法”部分。
还有一些关于 ScottGu's 博客的信息,包括用于在您的网络服务器上查找易受攻击的 ASP.Net 应用程序的 script。
有关“了解填充 Oracle 攻击”的说明,请阅读 @sri's answer。
文章评论:
Rizzo 和 Duong 对 ASP.NET 应用程序实施的攻击要求网站上的加密实施有一个预言机,当发送密文时,它不仅会解密文本,还会向发送者发送一条消息,说明密文中是否有填充已验证。如果填充无效,发件人收到的错误消息将为他提供有关站点解密过程工作方式的一些信息。
为了使攻击起作用,必须满足以下条件:
您的应用程序必须给出有关填充无效的错误消息。
必须有人篡改您的加密 cookie 或视图状态
因此,如果您在应用程序中返回人类可读的错误消息,例如“出现问题,请重试”,那么您应该是非常安全的。阅读一些关于文章的评论也可以提供有价值的信息。
在加密的 cookie 中存储会话 ID
以会话状态存储真实数据(保存在数据库中)
用户信息错误时添加随机等待返回错误,所以无法计时
这样,被劫持的 cookie 只能用于检索很可能不再存在或失效的会话。
看看 Ekoparty 会议上实际展示的内容会很有趣,但现在我不太担心这个漏洞。
了解填充 Oracle 攻击
让我们假设您的应用程序接受加密字符串作为参数 - 参数是 cookie、url 参数还是其他无关紧要的东西。当应用程序尝试对其进行解码时,有 3 种可能的结果 -
结果 1:加密字符串正确解密,应用程序能够理解它。意思是,如果加密的字符串是一个 10 位数的帐号,在解密后应用程序发现类似“1234567890”而不是“abcd1213ef”结果 2:填充是正确的,但在解密后获得的字符串是乱码,应用程序不能理解。例如,字符串解密为“abcd1213ef”,但应用程序只需要数字。大多数应用程序都会显示“无效帐号”之类的消息。结果 3:填充不正确,应用程序抛出了某种错误消息。大多数应用程序会显示一条通用消息,例如“发生了一些错误”。
为了使 Padding Oracle 攻击成功,攻击者必须能够发出数千个请求,并且必须能够将响应分类到上述 3 个桶之一中而不会出错。
如果满足这两个条件,攻击者最终可以解密消息,然后用他想要的任何方式重新加密它。这只是时间问题。
可以做些什么来预防它?
最简单的事情 - 任何敏感的东西都不应该发送给客户端,加密或不加密。保存在服务器上。确保上述列表中的结果 2 和结果 3 在攻击者看来完全相同。应该没有办法从另一个中找出一个。然而,这并不是那么容易——攻击者可以使用某种定时攻击来区分。作为最后一道防线,拥有一个 Web 应用程序防火墙。 padding oracle 攻击需要发出几个看起来几乎相似的请求(一次更改一位),因此 WAF 应该可以捕获并阻止此类请求。
PS 可以在 this blog post 中找到对 Padding Oracle Attacks 的一个很好的解释。免责声明:它不是我的博客。
从我读到现在...
该攻击允许某人解密嗅探到的 cookie,其中可能包含有价值的数据,例如银行余额
他们需要已在任何帐户上登录的用户的加密 cookie。他们还需要在 cookie 中查找数据——我希望开发人员不要将关键数据存储在 cookie 中:)。还有一种方法,我在下面不让 asp.net 将数据存储在登录 cookie 中。
如果没有掌握浏览器数据,如何获取在线用户的 cookie?或者嗅探IP数据包?
防止这种情况的一种方法是不允许 cookie 在没有 ssl 加密的情况下传输。
<httpCookies httpOnlyCookies="true" requireSSL="true" />
还有一项措施是防止将角色存储在 cookie 中。
<roleManager enabled="true" cacheRolesInCookie="false">
现在关于常规页面不安全的 cookie,这需要更多思考您让用户做什么和不做什么,您如何信任他,您可以做哪些额外检查(例如,如果您看到 ip 上的更改,也许在从安全页面重新登录之前停止信任他)。
参考:
Can some hacker steal the cookie from a user and login with that name on a web site?
如何检查攻击的来源而不返回信息。我在这里写了一个简单的方法来防止填充无效并同时记录以追踪攻击者:CryptographicException: Padding is invalid and cannot be removed and Validation of viewstate MAC failed
跟踪攻击者的方法是检查填充是否无效。通过一个简单的程序,您可以追踪并阻止他们 - 他们需要在您的页面上进行数千次调用才能找到关键!
更新 1。
我已经下载了假设找到密钥并解密数据的工具,正如我所说的它在 above code that's check the viewstate 上的陷阱。从我的测试来看,这个工具还有很多需要修复的地方,例如无法按原样扫描压缩视图状态以及它在我的测试中崩溃。
如果有人尝试使用此工具或此方法,上述代码可以追踪到它们,您可以使用像 "Prevent Denial Of Service (DOS)" 或 like this code for preventing Denial of service 这样的简单代码将它们阻止在您的页面之外。
更新 2
从我读到现在的内容看来,唯一的想法是真正需要它不提供有关错误的信息,而只是place a custom error page and if you like you can just create and a random delay to this page.
a very interesting video 关于这个问题。
因此,以上所有这些措施都是为了提供更多保护,但对于这个特定问题并不是 100% 的必要条件。例如,使用 ssl cookie 解决了 snif 问题,不缓存角色在 cookie 中最好不要发送和取回大 cookie,并避免一些已经准备好破解代码的人,只需将管理员角色放在他的饼干。
视图状态跟踪它只是另一种发现攻击的措施。
添加 ScottGu 在 http://weblogs.asp.net/scottgu/archive/2010/09/18/important-asp-net-security-vulnerability.aspx 的讨论中的回复
自定义 IHttpModule 而不是 customErrors 是否受影响?
问:我的 web.config 中没有声明元素,而是在该部分中声明了一个 IHttpModule。该模块记录错误并重定向到搜索页面(对于 404)或错误页面(对于 500)。我脆弱吗?
答:我建议暂时更新模块以始终重定向到搜索页面。这种攻击的工作方式之一是寻找 404 和 500 错误之间的区别。始终返回相同的 HTTP 代码并将它们发送到同一个地方是帮助阻止它的一种方法。
请注意,当补丁出来解决这个问题时,您不需要这样做(并且可以恢复到旧的行为)。但目前我建议不要对客户区分 404 和 500。
我可以继续对 404 和 500 错误使用不同的错误吗?
问:我认为除了默认的错误重定向之外,我们仍然可以定义自定义 404 页面,而不会违反上述原则?
答:不 - 在我们发布真正修复的补丁之前,我们建议使用上述解决方法,它可以使所有错误均质化。这种攻击的工作方式之一是寻找 404 和 500 错误之间的区别。始终返回相同的 HTTP 代码并将它们发送到同一个地方是帮助阻止它的一种方法。
请注意,当补丁出来解决这个问题时,您不需要这样做(并且可以恢复到旧的行为)。但是现在你不应该对客户区分 404 和 500。
这如何允许暴露 web.config?
问:这如何允许暴露 web.config?这似乎只启用了 ViewState 的解密,是否还有另一个相关的漏洞也允许信息泄露?是否有详细说明攻击的白皮书,以便更好地解释正在发生的事情?
答:公开展示的攻击依赖于 ASP.NET 中的一项功能,该功能允许下载文件(通常是 javascript 和 css),并使用作为请求的一部分发送的密钥进行保护。不幸的是,如果您能够伪造密钥,您可以使用此功能下载应用程序的 web.config 文件(但不能下载应用程序之外的文件)。我们显然会为此发布一个补丁——在此之前,上述解决方法会关闭攻击向量。
编辑:在 http://weblogs.asp.net/scottgu/archive/2010/09/20/frequently-asked-questions-about-the-asp-net-security-vulnerability.aspx 的第二篇博文中提供了其他常见问题解答
IMO,对此没有全面的预防措施,需要根据具体情况进行处理:
http://www.onpreinit.com/2010/09/aspnet-vulnerability-workaround-flawed.html
几个重要的链接:
MS 的安全公告 2416728(这是官方信息)
来自 MS 安全研究与防御团队的附加信息“了解 ASP.NET 漏洞”(2010-09-17)“关于 ASP.NET 漏洞的附加信息”(2010-09-20)
“了解 ASP.NET 漏洞” (2010-09-17)
“有关 ASP.NET 漏洞的附加信息” (2010-09-20)
Scott Gu:“重要:ASP.NET 安全漏洞”(2010-09-18)
[回答这个问题的严重性(已发布的内容和解决方法已包含在其他答案中)。]
被攻击的密钥用于保护视图状态和会话 cookie。通常,此密钥由 ASP.NET 在 Web 应用程序的每个新实例内部生成。这将限制对工作进程生命周期的损害范围,当然对于繁忙的应用程序来说,这可能是几天(即限制不大)。在此期间,攻击者可以将值更改(或注入)到 ViewState 并更改其会话。
更严重的是,如果您希望会话能够跨越工作进程的生命周期,或者允许网络场(即场中的所有实例都可以处理任何用户会话),则需要对密钥进行硬编码,这在 web.config
中完成:
[...]
<system.web>
<machineKey
decryption="AES"
validation="SHA1"
decryptionKey="57726C59BA73E8A4E95E47F4BC9FB2DD"
validationKey="158B6D89EE90A814874F1B3129ED00FB8FD34DD3"
/>
当然,这些是新创建的密钥,我使用以下 PowerShell 来访问 Windows 加密随机数生成器:
$rng = New-Object "System.Security.Cryptography.RNGCryptoServiceProvider"
$bytes = [Array]::CreateInstance([byte], 20)
$rng.GetBytes($bytes)
$bytes | ForEach-Object -begin { $s = "" } -process { $s = $s + ("{0:X2}" -f $_) } -end { $s}
(使用长度为 20 的数组进行验证,使用长度为 16 的解密密钥。)
除了修改公共错误页面以不泄漏特定错误之外,似乎是更改上述键(或循环工作进程,如果它们已经运行了一段时间)的好时机。
[编辑 2010-09-21:添加到顶部的链接]
在对这个问题进行额外研究后,我刚刚发布了我对这个 in my blog 的完整看法。我认为重要的是要弄清楚他们为什么要伪造一个 auth cookie。
只是想弄清楚一些事实:
攻击不允许您直接获取机器密钥。也就是说,它与它非常相似,因为它允许解密消息,并修改重新/加密新消息。获取实际密钥的方法是使用它们修改重新/加密的能力,如 1 并获取 web.config。不幸的是,有些人将这些密钥放在站点级别的 web.config 中是有原因的(不同的讨论),并且在示例视频中,他们受益于 DotnetNuke 的默认设置。获取所有的 web.config 表明他们正在使用 webresources.axd 和/或 scriptresources.axd。我认为这些仅适用于嵌入式资源,但似乎并非如此。如果应用程序是 asp.net MVC,我们真的不需要 webresources.axd 和/或 scriptresources.axd,所以可以关闭它们。我们也不使用视图状态。也就是说,我不清楚是否有任何其他 asp.net 功能在适当的解决方法中提供不同的信息,即我不知道填充是否在错误中给出无效结果,而在忽略身份验证票中填充有效结果(不知道如果是这样的话)......同样的分析应该适用于会话cookie。 cookie 中的 asp.net 会员提供程序“缓存”角色,将其关闭。
关于 1,afaik 加密的消息不能 100% 任意需要容忍消息中某处的一小块垃圾,因为消息中有 1 个块可以解密无法控制的值。
最后我想说这个问题是ms在这种情况下没有遵循自己的指导的结果:一个特性依赖于发送给客户端的东西是防篡改的。
更多关于:
我不知道填充是否在错误中给出无效结果,而在忽略的身份验证票中填充有效结果(不知道是否是这种情况)......同样的分析应该适用于会话 cookie。
auth cookie 是经过签名的,从论文中的信息来看,如果他们没有获得实际的密钥(就像他们在伪造 auth cookie 之前在视频中所做的那样),他们不应该能够生成签名的 cookie。
正如 Aristos 所提到的,对于 cookie 中的会话 ID,这对于用户会话是随机的,因此必须从具有目标安全级别的用户那里嗅探它,并在该会话处于活动状态时破解。即使那样,即使您依靠身份验证来分配/授权用户操作,那么影响也会很小/很大程度上取决于该应用程序中使用的 Session 。
此错误的修补程序已在 Windows 更新上发布:http://weblogs.asp.net/scottgu/archive/2010/09/30/asp-net-security-fix-now-on-windows-update.aspx
Asp.Net MVC 也受此问题的影响(Sharepoint 也是如此,...)
我在这里介绍了 MVC 的修复:Is ASP.NET MVC vulnerable to the oracle padding attack?
Roles.AddUserToRole("Joe", "Admin")
但我从未将其实际存储在 cookie 中,我是否安全?