c# – 如何防止在.NET中的DLL的欺骗

我有一个引用托管DLL的.NET应用程序。

这个DLL包含一个类,表示ScoreKeeper实现一个称为GetHighScore()的方法。应用程序定期调用它。

有没有办法阻止.NET应用程序使用“未授权”的DLL代替我提供的DLL?

你提到:

This DLL contains a class, say ScoreKeeper that implements a method called GetHighScore(). The application calls this periodically.

接着:

Is there a way to prevent the .NET application from using a “non-authorized” DLL here in place of the one I am supplying?

假设你想阻止某人交换出你已经提供的自己的程序集,它们具有相同的名称和类型(在同一个命名空间中),你可以将apply a strong name to the assembly包含在ScoreKeeper类中,并让你的消费者参考那。

但是,我们会看到有一些问题使得这不是100%可靠。强名称可帮助您保护不知情的用户免受恶意欺骗的副本替换您的DLL。但是如果用户在欺骗中是同谋的(如果他正在尝试欺骗就是这种情况),则代码签名将不过是速度障碍,也没有提供真正的保护。当然,强名不提供与例如相似的保护。 PunkBuster。

使用强名称来验证程序集发布者的身份

当您向程序集添加强名称时,您正在使用私钥(非对称的公钥/私钥对的一部分,稍后将更多的)生成加密散列,并且公钥包含在程序集名称中散列)。

使用公共哈希和公共密钥,CLR能够验证程序集的签名实际上是来自私钥。

当然,这意味着你应该保护钥匙(内部和外部);如果别人有你的钥匙,那么他们可以有效地模仿你,并发布人们会信任你的组件。

然后,当您添加对签名的程序集的引用时,如果有人尝试使用相同的程序集名称(而不是完全限定的程序集名称,仅使用不带版本,散列和公钥的名称)和相同类型名称放置其他程序集,那么尝试加载类型时,CLR填充失败,表示找不到;该类型将使用完全符合的程序集名称以及名称空间和类型名称来解析。

为什么强名不是100%安全(是吗?)

1)散列碰撞

它仍然是正在验证的哈希。虽然散列相当大(对于默认散列算法为SHA-1为160位),任何具有有限数值的散列都会发生冲突。虽然极不可能,但这是可能的(不可能的和不可能的)。此外,默认情况下仅使用最后8个字节。结合研究表明SHA-1相对较弱,这是使用MSDN所述的SHA-256增强型强名称的好理由。

2)删除强名

强名称可以删除。但是,在这种情况下,由于您的程序集为referencing the strong named version of the referenced assembly,当程序集尝试使用受损版本时,假定您已正确重新启用验证(见下文),则在运行时将失败。

3)对组件的物理访问意味着所有的组件

如果有人可以访问物理机,并且可以修改您所引用的程序集,那么程序集也是一样的脆弱。如果攻击者有能力修改您引用的程序集的强名称,那么它们可以轻松地修改程序集和执行中涉及的所有其他程序。为此,the only way to be 100% sure that the physical assembly isn’t hacked is to deny physical access through it.当然,这带来了许多不同的安全问题。

4)禁用强名称检查的管理员

计算机管理员可以简单地绕过强名称检查,使用sn -Vr。根据MSDN

Registers assembly for verification skipping… A malicious assembly could use the fully specified assembly name (assembly name, version, culture, and public key token) of the assembly added to the skip verification list to fake its identity. This would allow the malicious assembly to also skip verification.

5)必须在.NET 3.5 SP 1之后显式启用强名称检查

从.NET 3.5 SP 1开始,simply having a strong name doesn’t provide any protection

Starting with the .NET Framework version 3.5 Service Pack 1 (SP1), strong-name signatures are not validated when an assembly is loaded into a full-trust AppDomain object, such as the default AppDomain for the MyComputer zone.

为了让.NET检查加载到应用程序中的每个程序集的强名称,您需要将以下代码片段(由MSDN提供)插入到应用程序配置文件中:

06000

不过,请注意,这只能防止强名。

When you override the bypass feature, the strong name is validated only for correctness; it is not checked for a StrongNameIdentityPermission. If you want to confirm a specific strong name, you have to perform that check separately.

如果根据上述情况,您仍然希望强力命名您的装配,这里是如何。

生成一个强名称并签署你的程序集

生成一个强名称时可以使用两个选项。在Visual Studio中,转到项目属性的签名选项卡,然后单击“签署程序集”:

从那里,您有两个选项来生成公钥/私钥,让VS.NET为您生成密钥,或指向一个现有密钥:

当选择“新建”时,Visual Studio将提示您生成文件的名称,以及是否可以选择使用密码来访问它:

此时,密钥将添加到您的项目中:

现在,您可以将其移动到解决方案项目(如果您的解决方案中有多个项目)。

在这种情况下,Visual Studio实际上只是调用Strong Name command line tool来生成公钥和私钥对。如果你宁愿自己做,那么你可以使用-k命令行选项来调用sn.exe来生成密钥,如下所示:

sn -k keyPair.snk

然后通过上面的“浏览”对话框添加它。

请注意,当您这样做时,它将把钥匙拉入您的项目。如果您不想这样做(因为它将密钥复制到每个项目中),然后从项目中删除密钥,然后从add an existing file to the project, but link it中删除该密钥。这将清除“选择强名称密钥文件”选项,但如果删除您将看到链接的密钥文件的完整路径。

http://stackoverflow.com/questions/13346265/how-to-prevent-spoofing-of-dlls-in-net

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c# – 如何防止在.NET中的DLL的欺骗