为什么.NET不验证BCL/CLR?

6

BCL和CLR中的所有.NET程序集(之后仅使用CLR)都是强命名和数字签名。提供数字证书以提供一定程度的信任,表明程序集未被篡改或替换。然而,似乎.NET从未检查数字签名(它可以检查强名称,正如Hans 指出的那样)。

在程序集加载时进行检查是有缺陷的,因为修改过的CLR可能会伪造答案。我的想法是从.NET1的角度来看,唯一安全的检查地点是作为引导框架的非托管代码的一部分,在框架启动时进行检查。巨大的缺点是性能影响。

我从开发人员的角度考虑这个问题,换句话说,我如何知道我的应用程序没有被已拥有的CLR2破坏,或者换句话说,是否有任何方法让应用程序信任CLR?

所以我的问题是为什么.NET不验证CLR?是因为性能影响还是还有其他原因?
1. 我关注的是.NET,可能会干扰Windows并破坏这个想法,但如果你已经拥有Windows,你不需要拥有.NET。 2. 例如,用户将密码输入应用程序,它存储在SecureString中,但BCL已被攻击者入侵,因此攻击者现在可以获取该信息。这使他们能够捕获其他内容的信息。我意识到,如果攻击者可以替换CLR,他也可以在机器上放置键盘记录器,但这可以通过良好的安全工具进行检测(希望如此)。还有很多其他攻击方式,核心问题是如何知道SecureString是否已更改。
2个回答

6
这在.NET 3.5 SP1中有所改变,旨在为在完全信任下运行的应用程序提供与不进行此类检查的本地程序相同的性能改进(启动性能改进)。验证强名称是昂贵的,由于大量DLL文件的存在,托管程序的冷启动往往很慢。您可以通过.config文件将其重新打开:
<configuration>
    <runtime>
        <bypassTrustedAppStrongNames enabled="false"/>
    </runtime>
</configuration>

或者通过编辑注册表键值,使其对所有.NET程序生效:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]
"AllowStrongNameBypass"=dword:00000000

在64位机器上,还需设置HKLM\Software\Wow6432Node注册表项。


我没有将这个回答标记为最佳答案(我点了+1)的原因是它侧重于强名称而不是数字签名。强名称并不可靠,而数字签名应该在这方面有所帮助。 - Robert MacLean
我没有提到证书的原因是因为它们与.NET无关,只在文件传输或需要验证证书所有者身份的操作中进行检查。它们并不是用来防止篡改的。 - Hans Passant
数字证书与.NET相关,因为CLR由它们签名。数字签名可用于验证篡改(signtool verify /a <filename>),虽然在.NET中可能不会以这种方式使用,但它确实可以。既然可以这样使用,为什么不呢?更多信息 - Robert MacLean
我们必须就此达成不同意的共识。你的链接描述了强名称,它们*被用于检测篡改。我向你展示了如何重新启用验证。数字证书用于证明身份,这是完全不同的目标。而且昂贵,这无疑是它们在.NET中不被要求或以这种方式使用的主要原因。 - Hans Passant
成本、Verisign和类似公司为一个证书和年费收费约三百美元。 - Hans Passant
显示剩余2条评论

3
他们在GAC中。能够干扰GAC的人已经是特权用户了。此外,大多数应用程序运行在完全信任模式下,因此这是无关紧要的。因为在完全信任的应用程序中,您可以使用指针、本机互操作等,所有这些都可能破坏基于验证的安全性。
代码验证在执行低信任代码的情况下非常重要,例如在Silverlight中。在这样的沙盒中,您只想执行以下内容:
1. 经过验证的安全不受信任代码 2. 被信任的代码,它既在GAC中,也签署了您信任的密钥
这里已经有一个损坏的安全模型。在此威胁场景中,攻击应用程序的方式有很多种,您不需要担心BCL。例如,攻击者可以修补NGened或JITed代码。直接勾入SecureString方法或输入处理代码。他可以使用各种按键记录或消息拦截功能,在我所知道的情况下很少被检测到。他可以子类化你的窗口。您可以完全替换您的GUI。他甚至可以简单地替换您磁盘上的所有程序集。用户可能不会注意到。
根据我的经验,大多数安全工具甚至不关心应用程序是否安装了低水平键盘钩子,这是最简单的键日志方式之一。

GAC 的假设是错误的 - GAC 不会进行额外的检查,也不提供额外的信任。事实上,在那里替换程序集非常容易,没有强名称和数字签名。 - Robert MacLean
2
但前提是你在该机器上是管理员。 - CodesInChaos
我同意,如果您可以干扰全局程序集缓存(GAC),那么您可能不需要这样做,因为您已经拥有足够高的权限来控制机器。但是,这对于那些在系统上放置后门或隐藏监视的攻击是无济于事的 - 难道.NET不值得检查以减轻这些攻击吗? - Robert MacLean
不,这不是 .net 的职责。它怎么可能做到呢?即使是一个不受信任的用户也可以欺骗在他账户上运行的 .net,让它相信程序集是由其他人签名的。一旦你拥有了原始内存访问权限,你就拥有了该进程,并且 .net 不再是安全模型的一部分。这些东西的唯一用途是沙盒化代码并防止它以托管进程的特权执行任意代码。 - CodesInChaos
不,这并不是.NET该做的事情。 - 我的问题是为什么这不是.NET的职责?你说应用程序可以对计算机做任何事情,但是我怎么知道我的应用程序是否被拥有的BCL / CLR攻击了? - Robert MacLean
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接