关于.NET:这种新的ASP.NET安全漏洞有多严重,我如何解决它?

How serious is this new ASP.NET security vulnerability and how can I workaround it?

我刚刚在网上看到了ASP.NET中新发现的安全漏洞。您可以在这里阅读详细信息。

The problem lies in the way that
ASP.NET implements the AES encryption
algorithm to protect the integrity of
the cookies these applications
generate to store information during
user sessions.

这有点含糊,但更可怕的是:

The first stage of the attack takes a
few thousand requests, but once it
succeeds and the attacker gets the
secret keys, it's totally stealthy.The
cryptographic knowledge required is
very basic.

总而言之,我对安全/密码领域还不够熟悉,不知道这是否真的那么严重。

那么,所有的ASP.NET开发人员都应该害怕这种技术,它可以在几秒钟内拥有任何ASP.NET网站,还是什么?

此问题如何影响平均ASP.NET开发人员?它对我们有影响吗?在现实生活中,这种脆弱性的后果是什么?最后一点:是否有一些解决方案可以防止这种脆弱性?

谢谢你的回答!

编辑:让我总结一下我得到的回答

所以,这基本上是一种"填充甲骨文"类型的攻击。@SRI对这种类型的攻击意味着什么提供了一个很好的解释。这是一个令人震惊的关于这个问题的视频!

关于这个弱点的严重性:是的,它确实很严重。它允许攻击者了解应用程序的机器密钥。因此,他可以做一些非常不需要的事情。

  • 在应用程序的机器密钥会话中,攻击者可以解密身份验证cookie。
  • 更糟糕的是,他可以生成任何用户名的认证cookie。因此,他可以作为任何人出现在网站上。应用程序无法区分您和为自己生成带有您名字的身份验证cookie的黑客。
  • 它还允许他解密(并生成)会话cookie,尽管这不像前一个那样危险。
  • 不那么严重:他可以解密页面的加密视图状态。(如果使用viewstate存储机密数据,无论如何都不应该这样做!)
  • 非常出乎意料:有了机器密钥的知识,攻击者可以从您的Web应用程序下载任意文件,甚至那些通常无法下载的文件!(包括web.config等)

下面是我得到的一系列好的实践,这些实践并不能解决问题,但有助于提高Web应用程序的一般安全性。

  • 可以使用受保护的配置加密敏感数据
  • 仅使用HTTP cookie
  • 防止DoS攻击

现在,让我们集中讨论这个问题。

  • 斯科特·古思里在他的博客上发表了一篇关于它的文章。
  • Scottgu关于漏洞的常见问题博客帖子
  • Scottgu对漏洞的更新
  • 微软有关于它的安全建议
  • 了解漏洞
  • 有关漏洞的其他信息

解决方案

  • 启用customErrors并生成一个错误页,所有错误都将重定向到该页。是的,甚至是404。(斯科特古说,在404和500之间区分是这次攻击的关键。)同样,在你的Application_ErrorError.aspx中放入一些代码,使随机延迟。(生成一个随机数,然后使用thread.sleep休眠这么长时间。)这将使攻击者无法决定您的服务器上到底发生了什么。
  • 有些人建议切换回3DES。理论上,如果不使用AES,就不会在AES实现中遇到安全弱点。事实证明,根本不建议这样做。

其他一些想法

  • 似乎不是每个人都认为工作环境足够好。

感谢所有回答我问题的人。我不仅学到了这个问题,还学到了一般的网络安全。我将@mikael的答案标记为接受,但其他答案也非常有用。


我该怎么做才能保护自己?

[更新2010-09-29]

Microsoft安全公告

关于修复的知识库文章

Scottgu有下载链接

[更新2010-09-25]

在我们等待修复的同时,Scottgu昨天发布了一个关于如何添加额外步骤的更新,以使用自定义的URLScan规则保护您的站点。


基本上,请确保您提供了一个自定义错误页,这样攻击者就不会暴露于内部.NET错误中,无论如何,在发布/生产模式中都应该这样做。

另外,在错误页面中添加一个随机时间睡眠,以防止攻击者对添加的攻击信息的响应进行计时。

在Web.CONFIG中

1
2
3
4
5
6
7
<configuration>
 <location allowOverride="false">
   <system.web>
     <customErrors mode="On" defaultRedirect="~/error.html" />
   </system.web>
 </location>
</configuration>

这会将任何错误重定向到返回的带有200状态代码的自定义页。这样攻击者就无法查看错误代码或错误信息,以获取进一步攻击所需的信息。

设置customErrors mode="RemoteOnly"也是安全的,因为这将重定向"真正的"客户机。只有从本地主机浏览才会显示内部.NET错误。

重要的是确保所有错误都配置为返回相同的错误页。这要求您在部分显式设置defaultRedirect属性,并确保没有设置每个状态代码。

有什么危险?

如果攻击者设法使用上述漏洞,他/她可以从Web应用程序中下载内部文件。通常web.config是一个目标,它可能包含敏感信息,如数据库连接字符串中的登录信息,甚至链接到您不希望有人控制的自动路由SQL Express数据库。但是,如果您遵循最佳实践,则可以使用受保护的配置来加密web.config中的所有敏感数据。

指向引用的链接

在http://www.microsoft.com/technet/security/advisory/2416728.mspx上阅读Microsoft对该漏洞的官方评论。具体来说,这个问题的实施细节的"解决方法"部分。

还有一些关于Scottgu博客的信息,包括一个脚本,用于在Web服务器上查找易受攻击的ASP.NET应用程序。

有关"理解填充甲骨文攻击"的解释,请阅读@sri的答案。

文章评论:

The attack that Rizzo and Duong have implemented against ASP.NET apps requires that the crypto
implementation on the Web site have an oracle that, when sent ciphertext, will not only decrypt the text
but give the sender a message about whether the padding in the ciphertext is valid.

If the padding is invalid, the error message that the sender gets will give him some information about the way that the site's decryption process works.

要使攻击生效,必须满足以下条件:

  • 应用程序必须给出有关填充无效的错误消息。
  • 必须有人篡改加密的cookie或viewstate

因此,如果您在应用程序中返回人类可读的错误消息,比如"出错了,请再试一次",那么您应该非常安全。读一点关于这篇文章的评论也能提供有价值的信息。

  • 在加密的cookie中存储会话ID
  • 在会话状态下存储真实数据(持久化在数据库中)
  • 在返回错误之前,在用户信息错误时添加一个随机等待,这样您就无法对其计时。

这样一来,被劫持的cookie只能用于检索一个很可能不再存在或失效的会话。

在ekoparty会议上看到了什么是很有趣的,但是现在我不太担心这个弱点。


了解填充Oracle攻击

假设您的应用程序接受一个加密字符串作为参数-无论该参数是cookie、url参数还是其他一些无关紧要的参数。当应用程序尝试对其进行解码时,有3种可能的结果-

  • 结果1:加密字符串被正确解密,应用程序能够理解它。也就是说,如果加密的字符串是一个10位的帐号,那么在解密之后,应用程序会发现类似"1234567890"而不是"abcd1213ef"的内容。

  • 结果2:填充是正确的,但解密后得到的字符串是胡言乱语,应用程序无法理解。例如,字符串被解密为"abcd1213ef",但应用程序只需要数字。大多数应用程序都会显示一条类似"无效帐号"的消息。

  • 结果3:填充不正确,应用程序引发了某种类型的错误消息。大多数应用程序都会显示一条普通消息,比如"发生了一些错误"。

  • 为了使填充Oracle攻击成功,攻击者必须能够发出数千个请求,并且必须能够将响应分类为上述3个bucket中的一个,而不会出错。

    如果满足这两个条件,攻击者最终可以解密消息,然后根据自己的意愿重新加密。只是时间问题。

    我们可以做些什么来防止它?

  • 最简单的事情-任何敏感的东西都不应该发送到客户端,加密或不加密。把它放在服务器上。

  • 确保上面列表中的结果2和结果3对攻击者显示完全相同。不应该有办法从另一个中找出一个。不过,这并不是那么简单——攻击者可以使用某种定时攻击来区分。

  • 作为最后一道防线,有一个Web应用防火墙。padding-oracle攻击需要做出几个看起来几乎相似的请求(一次改变一位),因此WAF应该可以捕获和阻止此类请求。

  • 另外,在这篇博文中可以找到一个很好的关于填充甲骨文攻击的解释。免责声明:这不是我的博客。


    从我读到现在…

    The attack allows someone to decrypt
    sniffed cookies, which could contain
    valuable data such as bank balances

    他们需要已经登录的用户的加密cookie。他们还需要在cookie中查找数据-我希望开发人员不要将关键数据存储在cookie中:)。下面有一种方法,我不能让ASP.NET将数据存储在登录cookie中。

    如果用户不掌握浏览器数据,他怎么能得到在线用户的cookie呢?或者嗅探IP包?

    防止这种情况的一种方法是不允许没有SSL加密的cookie传输。

    1
    <httpCookies httpOnlyCookies="true" requireSSL="true" />

    另外一个措施是防止在cookie中存储角色。

    1
    <roleManager enabled="true" cacheRolesInCookie="false">

    现在,对于常规页面不安全的cookie,这需要更多的思考您留给用户做什么,不做什么,您如何信任他,您可以做什么额外的检查(例如,如果您在IP上看到更改,可能停止信任他,直到从安全页面重新登录)。

    参考文献:一些黑客能从用户那里窃取cookie并在网站上用这个名字登录吗?

    如何检查攻击的来源,而不返回信息。我在这里写了一个简单的方法来防止填充无效,同时记录以跟踪攻击者:CryptographicException:填充无效且无法删除,并且验证viewstate MAC失败

    跟踪攻击者的方法是检查填充是否无效。通过一个简单的过程,你可以追踪并阻止他们-他们需要在你的页面上调用数千次来找到密钥!

    更新1。

    我下载了一个工具,假设它找到了密钥并解密了数据,正如我所说,它在上面的代码上的陷阱检查了视图状态。从我的测试来看,这个工具还有很多要修复的地方,例如不能扫描压缩视图的状态,因为它在我的测试中崩溃了。

    如果有人试图使用此工具或此方法,上面的代码可以跟踪它们,您可以使用类似于此"防止拒绝服务(DoS)"的简单代码或类似于此代码的代码来阻止它们离开您的页面。

    更新2

    从我读到现在为止,似乎唯一认为真正需要它的是,不提供有关错误的信息,只需放置一个自定义错误页面,如果你愿意,你可以创建和随机延迟这个页面。

    关于这个问题的非常有趣的视频。

    因此,上述措施更多地是为了获得更多的保护,而不是这个特定问题的100%必需品。例如,使用ssl cookie可以解决snif问题,不缓存cookie中的角色,最好不要发送和返回大的cookie,并且避免一些已经准备好破解代码的cookie,只需将管理角色放在他的cookie上。

    视图状态只跟踪它的另一个发现攻击的度量。


    添加scottgu在http://weblogs.asp.net/scottgu/archive/2010/09/18/important-asp-net-security-viability.aspx上讨论的回复。

    自定义IHttpmodule而不是customerErrors是否受到影响?

    问:我的web.config中没有声明元素,而是在该节中声明了一个IHttpmodule。此模块记录错误并重定向到搜索页(对于404)或错误页(对于500)。我脆弱吗?

    答:我建议暂时更新模块,以始终重定向到搜索页面。这种攻击的工作方式之一是寻找404和500个错误之间的区别。始终返回相同的HTTP代码并将它们发送到相同的位置是帮助阻止它的一种方法。

    注意,当补丁出来修复这个问题时,您不需要这样做(并且可以恢复到以前的行为)。但现在我建议客户不要区分404和500。

    对于404和500个错误,我可以继续使用不同的错误吗?

    问:我认为,除了默认的错误重定向之外,我们还可以定义一个自定义404页面,而不违反上面描述的原则?

    答:没有-在我们发布真正修复补丁之前,我们建议采用上面的解决方法,使所有错误都同化。这种攻击的工作方式之一是寻找404和500个错误之间的区别。始终返回相同的HTTP代码并将它们发送到相同的位置是帮助阻止它的一种方法。

    注意,当补丁出来修复这个问题时,您不需要这样做(并且可以恢复到以前的行为)。但是现在你不应该把404和500S区别给客户。

    这如何允许web.config的曝光?

    问:这如何允许暴露web.config?这似乎只允许对viewstate进行解密,是否还有其他相关的漏洞允许信息公开?是否有一份详细说明攻击的白皮书,以便更好地解释发生了什么?

    答:公开显示的攻击依赖于ASP.NET中允许下载文件(通常是javascript和css)的功能,该功能由作为请求一部分发送的密钥进行保护。不幸的是,如果您能够伪造密钥,那么您可以使用此功能下载应用程序的web.config文件(但不能下载应用程序外部的文件)。显然,我们将为此发布一个补丁——直到上述解决方案关闭攻击向量。

    编辑:第二个blogpost中提供的其他常见问题解答,网址为http://weblogs.asp.net/scottgu/archive/2010/09/20/frequency-asked-questions-about-the-asp-net-security-viability.aspx


    这是微软的回应。这一切归根结底都是"使用自定义错误页",你不会泄露任何线索。

    编辑以下是斯科特古的一些更详细的信息。


    IMO,对此没有全面预防,需要逐个处理:

    http://www.onpreinit.com/2010/09/aspnet-viability-workaround-defected.html


    几个重要的环节:

    • 女士安全咨询2416728(这是官方信息)
    • 微软安全研究与防御团队提供的其他信息
      • "了解ASP.NET漏洞"(2010-09-17)
      • "有关ASP.NET漏洞的其他信息"(2010-09-20)
    • Scott Gu:"重要:ASP.NET安全漏洞"(2010-09-18)

    [回答这方面的严重性问题(已发布的内容和解决方法包含在其他答案中)。]

    被攻击的密钥用于保护视图状态和会话cookie。通常情况下,此键由ASP.NET内部生成,每个Web应用程序的新实例都包含此键。这将限制对工作进程生命周期的损害范围,当然对于繁忙的应用程序,这可能是几天(即不太多的限制)。在此期间,攻击者可以更改(或注入)视图状态的值并更改其会话。

    更严重的是,如果您希望会话能够跨越工作进程的生命周期,或者允许Web场(即场中的所有实例都可以处理任何用户会话),则需要对密钥进行硬编码,这在web.config中完成:

    1
    2
    3
    4
    5
    6
    7
    8
    [...]
      <system.web>
        <machineKey
            decryption="AES"
            validation="SHA1"
            decryptionKey="57726C59BA73E8A4E95E47F4BC9FB2DD"
            validationKey="158B6D89EE90A814874F1B3129ED00FB8FD34DD3"
          />

    当然,这些是新创建的密钥,我使用以下PowerShell访问Windows加密随机数生成器:

    1
    2
    3
    4
    $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:添加顶部链接]


    已在Windows Update上发布此Bug的修补程序:http://weblogs.asp.net/scottgu/archive/2010/09/30/asp-net-security-fix-now-on-windows-update.aspx


    在对这个问题做了额外的研究之后,我刚刚在博客上发表了我对这个问题的全部看法。我认为很重要的一点是要弄清楚他们为什么要伪造一个认证cookie。

    只是想弄清楚一些事实:

  • 攻击不能让你直接拿到机器钥匙。也就是说,它和以前的非常相似,因为它允许解密消息,并修改重新/加密新的消息。
  • 获取实际密钥的方法是使用它们的功能,如1中所示修改重新/加密并获取web.config。不幸的是,有一些人将这些密钥放在网站级别的web.config中(不同的讨论),在示例视频中,它们受益于dotnetnuke的默认设置。
  • 要获得web.config,所有这些都指向他们正在使用webresources.axd和/或scriptreurces.axd。我认为这些只适用于嵌入式资源,但似乎不是这样。
  • 如果应用程序是ASP.NET MVC,我们实际上不需要WebResources.axd和/或ScriptResources.axd,因此可以关闭它们。我们也不使用viewstate。也就是说,我不清楚其他任何ASP.NET功能是否在适当的解决方案中提供了不同的信息,也就是说,我不知道padding在将有效结果填充到被忽略的身份验证票证时是否会给出错误的无效结果(不知道其大小写是否正确)。同样的分析也应该应用于会话cookie。
  • ASP.NET成员资格提供程序在cookie中"缓存"角色,请关闭该选项。
  • 大约1,afaik加密的消息不能是100%任意的,需要在消息中的某个地方容忍一小块垃圾,因为消息中有一个块可以解密无法控制的值。

    最后,我想说的是,这个问题是MS在这种情况下没有遵循它自己的指导:一个特性依赖于发送给客户机的东西是防篡改的。

    更多关于:

    I don't know if padding gives invalid results in error while padding valid results in ignored authentication ticket (don't know if its or not the case) ... the same analysis should apply to the session cookie.

    认证cookie是签名的,根据文件中的信息,如果他们没有得到实际的密钥,他们就不能生成签名cookie(就像他们在伪造认证cookie之前在视频中所做的那样)。

    正如亚里士多德提到的,对于cookie中的会话ID,这对于用户会话是随机的,因此必须从目标安全级别的用户那里嗅到它,并在会话处于活动状态时将其破解。即使这样,如果您依靠身份验证来分配/授权用户操作,那么影响也会很小/很大程度上取决于该应用程序中使用的会话。


    ASP.NET MVC也受此问题的影响(如SharePoint…)

    我在这里介绍了MVC的修复方法:ASP.NET MVC是否容易受到Oracle填充攻击?