20

MSDN 在这篇文章上说:

CLR 使用 .NET Framework 中的代码访问安全性 (CAS),不再支持将其作为安全边界。使用 PERMISSION_SET = SAFE 创建的 CLR 程序集可能能够访问外部系统资源、调用非托管代码并获得系统管理员权限。从 SQL Server 2017 开始,引入了一个名为 clr strict security 的 sp_configure 选项,以增强 CLR 程序集的安全性。默认情况下启用 clr strict security,并将 SAFE 和 EXTERNAL_ACCESS 程序集视为标记为 UNSAFE。为了向后兼容,可以禁用 clr strict 安全选项,但不建议这样做。Microsoft 建议使用证书或非对称密钥对所有程序集进行签名,并使用已在 master 数据库中授予 UNSAFE ASSEMBLY 权限的相应登录名。

创建的 CLR 程序集如何PERMISSION_SET = SAFE能够访问外部系统资源、调用非托管代码并获得系统管理员权限?

为什么不再支持 CAS 作为安全边界?

据我了解,CLR 程序集不再是安全的,这是非常不幸的。

4

3 回答 3

25

我知道这不是一个真正的解决方案,但您可以更改安全模式:

EXEC sp_configure 'show advanced options', 1
RECONFIGURE;
EXEC sp_configure 'clr strict security', 0;
RECONFIGURE;

对于那些想要继续工作的人来说,这是最简单的解决方案

于 2019-05-12T05:05:29.103 回答
24

使用 PERMISSION_SET = SAFE 创建的 CLR 程序集如何能够访问外部系统资源、调用非托管代码并获得系统管理员权限?

这是由于从 4.5 版(我相信)开始在 .NET Framework 中进行的安全更改。

代码访问安全基础知识的 MSDN 文档指出:

.NET Framework 提供了一种机制,用于对运行在同一应用程序中的不同代码实施不同级别的信任,称为代码访问安全 (CAS)。.NET Framework 中的代码访问安全性不应用作基于代码来源或其他身份方面强制实施安全边界的机制。我们正在更新我们的指南,以反映代码访问安全性和安全透明代码将不被支持作为部分受信任代码的安全边界,尤其是未知来源的代码。我们建议不要在未采取替代安全措施的情况下加载和执行来源不明的代码。

然后指向.NET Framework 中的安全更改页面,其中指出:

.NET Framework 4.5 中对安全性最重要的更改是强命名。

然后指向增强强命名的文档,其中指出:

强名称密钥由签名密钥和身份密钥组成。程序集使用签名密钥进行签名,并由身份密钥标识。在 .NET Framework 4.5 之前,这两个键是相同的。从 .NET Framework 4.5 开始,标识密钥与早期 .NET Framework 版本中的相同,但签名密钥通过更强大的哈希算法得到了增强。此外,签名密钥使用身份密钥进行签名以创建副签名。

此外,安全编码指南的文档指出:

不支持代码访问安全性和安全透明代码作为部分受信任代码的安全边界。我们建议不要在没有采取替代安全措施的情况下加载和执行来源不明的代码......

因此,.NET 的安全模型几年前发生了变化,但 SQL Server(直到 SQL Server 2017)已被允许继续使用旧的安全模型。从 SQL Server 2017 开始,似乎决定不再支持旧的安全模型。

我怀疑允许旧的安全模型是:

  • 防止 SQL Server(至少是与 CLR 相关的功能/组件)基于较新的 .NET Framework 版本,以及

  • 负责从 Azure SQL 数据库中突然删除 SQLCLR 作为支持的功能(支持已在 2014 年底随着 v12 的推出而添加,但随后在 2016 年 4 月 15 日完全删除)。


所以,是的,这有点糟糕。这意味着(至少目前)是需要首先创建一个证书或非对称密钥(已用于签署要加载的任何程序集)[master],然后创建一个登录名,然后授予UNSAFE ASSEMBLY该登录名。EXTERNAL_ACCESS这与加载和程序集时需要执行的事件序列相同UNSAFE,但不幸的是,现在甚至需要为程序集完成SAFE

目前没有机制以完全可移植的方式(即不依赖外部文件)处理此问题,并且在没有手动干预的情况下无法由 Visual Studio / SSDT 处理。情况已经如此,但至少可以创建一个设置来以完全可移植的方式处理这个问题(即完全包含在 .sql 脚本中):请参阅SQLCLR 7 级的阶梯:开发和安全了解详细信息(这是我写的一篇文章)。

可以从十六进制字节FROM BINARY = 0x...signtoolsn.

为了使它可行,以便 Visual Studio / MSBuild / SSDT 发布过程正常工作(这反过来意味着任何人都可以创建一个完全独立的 .sql 脚本,该脚本能够创建非对称密钥而无需依赖外部文件),CREATE ASYMMETRIC KEY需要增强该命令以允许从二进制字符串创建。我在 Microsoft Connect 上提出了这个建议——允许从二进制十六进制字节字符串创建非对称密钥,就像 CREATE CERTIFICATE 一样——所以请支持它:-)。

或者(目前,直到 MS 希望创建更好的方法,例如我的非对称密钥建议),您可以尝试我在以下博客文章中描述的两种技术中的任何一种(都可以与 SSDT 完全配合):

作为最后的手段,您可以考虑以下方法:

  1. 暂时[master]数据库设置为TRUSTWORTHY ON

    为使下一步(即CREATE ASSEMBLY)成功执行,作为数据库所有者的登录名(即与[dbo]用户使用相同的 SID [master])需要具有UNSAFE ASSEMBLY权限。如果[master]sa或任何其他系统管理员拥有,则它具有所有权限并且已满足此要求。但是,如果[master]由低权限登录拥有(“最佳实践”),那么您将需要执行以下语句才能在isCREATE ASSEMBLY时工作:TRUSTWORTHYON

    EXEC (N'USE [master]; GRANT UNSAFE ASSEMBLY TO [{DB_Owner_Login}];');
    
  2. 在中创建装配体[master]
  3. 从程序集中创建非对称密钥
  4. 删除程序集
  5. [master]数据库设置为TRUSTWORTHY OFF
  6. 从非对称密钥创建登录
  7. 授予UNSAFE ASSEMBLY该登录名(这取代了将加载程序集的数据库设置为TRUSTWORTHY ON 及其所有者登录名具有UNSAFE ASSEMBLY权限的需要)。

请注意,我没有此处包含新的“受信任的程序集”功能作为选项。没有提到它的原因是它的缺陷多于好处,更不用说它完全没有必要,因为现有功能已经处理了“受信任的程序集”旨在解决的情况。有关这方面的完整详细信息以及处理现有未签名程序集的正确方法的演示,请参阅:SQLCLR 与 SQL Server 2017,第 4 部分:“受信任的程序集” - 失望

于 2017-05-20T13:46:31.747 回答
2

前几天我遇到了这个问题,它似乎并不像听起来那么糟糕(除了你不能再创建一个安全的程序集,而是需要对其进行签名等,或者使用 TRUSTWORTHY)。

在我的测试中:

  • 我创建了一个具有“安全”方法和“不安全”(它使用了任务)的程序集。
  • 我将程序集创建为 SAFE(在构建并签名后等)
  • 我围绕我的两种方法创建了 T-SQL 包装函数。
  • 执行“安全”功能时,一切正常。
  • 执行“UNSAFE”时,我收到了 HostProtectionException。

对我来说,这表明对正在执行的内容仍有一些控制。我跟进了:

  • 使用 PERMISSION_SET = UNSAFE 重新创建程序集
  • 重新创建函数
  • 现在,当我执行 UNSAFE 功能时,一切都按预期工作。

所以我不太确定“clr strict security”文档中的陈述是否 100% 正确。

我写了一篇关于我的经历的博文,如果你想自己测试一下,可以在这里找到:http: //www.nielsberglund.com/2017/07/02/sql-server-2017-sqlclr-and -权限/

尼尔斯

于 2017-07-02T07:17:29.070 回答