1

在创建 SQL Server CLR 存储过程时,我注意到我无法像往常一样引用 .net 框架中的任何内容。经过一番阅读,我意识到需要先将程序集加载到数据库中。

因此,我加载了我需要的那些,但由于 P/Invoke 不得不使用 UNSAFE 权限集。我现在可以在我的存储过程代码中引用它们并且一切正常。

但是,当我真的不知道他们在做什么时,我有点担心必须将它们设置为 UNSAFE。所以我的问题是:

可以将 .net 框架加载为 UNSAFE 而不完全按照它在做什么?这样做会如何损害 sql server 的安全性/健壮性/可扩展性(正如微软警告的那样)?

非常感谢。

4

3 回答 3

2

它可以更改注册表、重新启动服务、重新启动服务器等。没有什么太重要了 ;-) 一个简单的图表,其中包含不同之处

也请参阅此问题(虽然没有答案)SQL Server 2008: How crash-safe is a CLR Stored Procedure that load unmanaged libraries

当然,您在做什么需要不安全的访问权限?

于 2009-04-21T10:18:15.433 回答
0

这个问题专门针对加载不在Supported .NET Framework Libraries集中的 .Net Framework 程序集,因此我将重点关注 Microsoft 提供的 DLL 而不是任何随机 DLL 的上下文。

“支持”列表中的程序集和不在列表中的程序集之间的区别归结为支持的程序集“已经过测试,以确保它们符合与 SQL Server 交互的可靠性和安全标准”(如上面链接的“支持的库”页面)。主要问题是“可靠性”而不是“安全性”。支持列表中的程序集已经过验证,其行为与预期一致,没有任何错误或奇怪的副作用。该功能已经过测试,可以使用各种语言和排序规则等。

一些不在支持列表中的 .Net Framework 程序集可以加载PERMISSION_SETSAFE. 但是,这并不能保证所需的行为。并且有些可以加载为UNSAFE不一定说明会有问题。

作为不保证行为的示例:我已加载System.Drawing以进行一些简单的图像处理。当图像直接通过byte[]/VARBINARY(MAX)提供时以及由文件路径提供并从磁盘读取时,我测试了操作。一切都按预期工作。我把它发给了德国的某个人,他的 Windows 和 SQL Server 都设置为“德语”作为语言。直接提供图像时,他能够得到预期的结果。但是当他提供文件路径时它不起作用。

对于不希望的行为,SQL Server 将显示程序集无法加载的原因SAFEEXTERNAL_ACCESS当您尝试加载时。例如:

CREATE ASSEMBLY [System.Drawing]
AUTHORIZATION [dbo]
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Drawing.dll'
WITH PERMISSION_SET = SAFE;

结果是:

警告:Microsoft .NET Framework 程序集 'system.drawing,version=4.0.0.0,culture=neutral,publickeytoken=b03f5f7f11d50a3a,processorarchitecture=msil。' 您注册的内容未在 SQL Server 托管环境中进行全面测试,因此不受支持。将来,如果您升级或维修此程序集或 .NET Framework,您的 CLR 集成例程可能会停止工作。有关详细信息,请参阅 SQL Server 联机丛书。

消息 6218,级别 16,状态 2,第 1 行为
程序集“System.Drawing”创建程序集失败,因为程序集“System.Drawing”验证失败。检查引用的程序集是否是最新的并且受信任(对于 external_access 或不安全)以在数据库中执行。如果有任何 CLR 验证程序错误消息将跟随此消息

[ : System.Drawing.BufferedGraphicsContext::bFillColorTable][mdToken=0x600013c][offset 0x00000053][found address of Byte] 堆栈上的预期数字类型。

[ : System.Drawing.BufferedGraphicsContext::bFillColorTable][mdToken=0x600013c][offset 0x00000043][found Native Int][expected address of Byte] 堆栈上的意外类型。

[ : System.Drawing.BufferedGraphicsContext::bFillColorTable][mdToken=0x600013c][offset 0x00000027][found Native Int][expected address of Byte] 堆栈上的意外类型。

[ : System.Drawing.Icon::ToBitmap][mdToken=0x6000349][offset 0x00000084][found unmanaged pointer][expected unmanaged pointer] 堆栈上的意外类型。

[ : System.Drawing.Icon::ToBitmap][mdToken=0x6000349][offset 0x000000E4] 非托管指针不是可验证的类型。

[ : System.Drawing.Icon::GetShort][mdToken=0x6000356][offset 0x00000002] 非托管指针不是可验证的类型。
...

如果您不打算使用任何这些方法或类型,那么您可能不会遇到任何问题。没有办法将“安全”的东西与“不安全”的物品分开。

另一个关联内疚的例子,但甚至更远,是:

CREATE ASSEMBLY [System.Web]
AUTHORIZATION [dbo]
FROM 'C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Web.dll'
WITH PERMISSION_SET = SAFE;

结果是:

警告:Microsoft .NET Framework 程序集 'system.web,version=4.0.0.0,culture=neutral,publickeytoken=b03f5f7f11d50a3a,processorarchitecture=x86。' 您注册的内容未在 SQL Server 托管环境中进行全面测试,因此不受支持。将来,如果您升级或维修此程序集或 .NET Framework,您的 CLR 集成例程可能会停止工作。有关详细信息,请参阅 SQL Server 联机丛书。

警告:Microsoft .NET Framework 程序集 'microsoft.build.framework,version=4.0.0.0,culture=neutral,publickeytoken=b03f5f7f11d50a3a,processorarchitecture=msil。' 您注册的内容未在 SQL Server 托管环境中进行全面测试,因此不受支持。将来,如果您升级或维修此程序集或 .NET Framework,您的 CLR 集成例程可能会停止工作。有关详细信息,请参阅 SQL Server 联机丛书。

警告:Microsoft .NET Framework 程序集 'system.xaml,version=4.0.0.0,culture=neutral,publickeytoken=b77a5c561934e089,processorarchitecture=msil。' 您注册的内容未在 SQL Server 托管环境中进行全面测试,因此不受支持。将来,如果您升级或维修此程序集或 .NET Framework,您的 CLR 集成例程可能会停止工作。有关详细信息,请参阅 SQL Server 联机丛书。

消息 6212,级别 16,状态 1,第 1 行
CREATE ASSEMBLY 失败,因为安全程序集“System.Xaml”中类型“System.Windows.Markup.ValueSerializer”的方法“TypeDescriptorRefreshed”正在存储到静态字段。在安全程序集中不允许存储到静态字段。

如您所见,System.Web实际上,它本身就很好SAFE,但它具有依赖程序集并且正在自动加载。第一个依赖程序集microsoft.build.framework也没有问题(至少不能验证,尽管有可能不允许SAFE是否存在但只能在运行时捕获)。但是第二个依赖程序集确实有一个可以在加载程序集时验证的问题:它“存储到静态字段”。这是一个可靠性问题而不是安全性问题,因为类被实例化一次(嗯,每个应用程序域,意味着:每个数据库,每个所有者)并在 SPID 之间共享以供使用(这就是为什么在 SQLCLR 中只能访问静态方法的原因) . 因此,静态类级变量在技术上是在会话(即 SPID)之间共享信息,这很容易导致意外行为。但同时,如果您只想使用HtmlString.ToHtmlString(),那么您可能没有使用System.Xaml. 那么为什么它不只是加载System.WebasSAFESystem.XamlasUNSAFE呢?可能是因为代码在SAFE程序集不允许调用程序集中的代码UNSAFE(至少在 SQLCLR 中不允许)。

结论
那么加载UNSAFE.Net Framework 程序集可以吗?这真的应该归结为测试。大量的测试(不仅仅是你的开发箱上的一个线程,而是真正的测试)。如果一切都按预期运行,那么你应该没问题。但是,如果某些行为与预期不符,那么它不是可以报告给 Microsoft 的错误,因为它已被声明为不受支持。


编辑:
这里是这个问题的更正式的答案,其中列出了可能出现问题的几种情况:SQL Server CLR-hosted environment 中未经测试的 .NET Framework 程序集的支持策略

于 2014-11-18T17:10:35.053 回答
0

当您在托管许多公共网站的服务器上使用 SQL 数据库引擎时,您作为服务器管理员(或 DBA 或任何负责人)一无所知,您应该限制他们的访问,这很重要!此外,如果您在受限区域拥有 DBA,在某些大公司中数据最重要的地方,这也是最重要的事情。

在我看来,你应该给你的应用程序提供它需要看到的东西,仅此而已。例如,如果您不需要查看注册表,为什么要授予对程序集的无限制访问权限?您不知道如果有人将您的应用程序的代码注入并劫持到数据库中(也可以不受限制地访问!)会有多危险。

希望能帮助到你

于 2013-01-30T10:47:56.040 回答