可以将.net dll作为UNSAFE加载到SQL Server中吗?

时间:2009-04-21 08:14:15

标签: sql-server sql-server-2005 clr sqlclr

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

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

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

是否可以将.net框架作为UNSAFE加载而不完全正在做什么? 如何这样做会破坏sql server的安全性/健壮性/可伸缩性(正如微软警告它可能的那样)?

非常感谢。

3 个答案:

答案 0 :(得分:2)

它可以更改注册表,重新启动服务,重新启动服务器等。没什么太重要的;-)一个简单的chart with the differences

也可以看到这个问题(虽然没有答案)SQL Server 2008: How crash-safe is a CLR Stored Procedure that loads unmanaged libraries

当然,你在做什么需要UNSAFE访问?

答案 1 :(得分:0)

当您在托管许多公共网站的服务器上使用SQL数据库引擎时,您不了解作为服务器管理员(或DBA或负责任何人)的任何信息,您应该限制他们的访问并且该死的#&# 39;重要!此外,如果您在限制区域拥有DBA,数据在某些大公司中最为重要,那么它也是最重要的事情。

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

希望有所帮助

答案 2 :(得分:0)

此问题特定于加载不在Supported .NET Framework Libraries集合中的.Net Framework程序集,因此我将重点介绍Microsoft提供的DLL而不是任何随机DLL的上下文。

"支持"中的组件之间的差异;列表和不在列表中的列表归结为受支持的列表已经过测试,以确保它们符合与SQL Server交互的可靠性和安全性标准。 (如"支持的库"上面链接的页面中所述)。主要问题更多的是"可靠性"而不是"安全"。受支持列表中的程序集已经过验证,其行为符合预期,并且没有任何错误或奇怪的副作用。该功能已经过测试,可以使用各种语言和校对等。

某些不在受支持列表中的.Net Framework程序集可以加载PERMISSION_SET设置为SAFE。然而,这并不能保证所期望的行为。有些可以加载为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;抽象,版本= 4.0.0.0,culture = neutral,publickeytoken = b03f5f7f11d50a3a,processorarchitecture = msil。'您正在注册未在SQL Server托管环境中进行全面测试,并且不受支持。将来,如果升级或维护此程序集或.NET Framework,则CLR集成例程可能会停止工作。有关更多详细信息,请参阅SQL Server联机丛书。

     

Msg 6218,Level 16,State 2,Line 1
  为汇编' System.Drawing'创建汇编。失败,因为汇编' System.Drawing'验证失败。检查引用的程序集是否是最新的并且在数据库中是否可信(对于external_access或unsafe)。 CLR Verifier错误消息(如果有的话)将跟随此消息

     

[:System.Drawing.BufferedGraphicsContext :: bFillColorTable] [mdToken = 0x600013c] [offset 0x00000053] [找到字节的地址]堆栈上的预期数字类型。

     

[:System.Drawing.BufferedGraphicsContext :: bFillColorTable] [mdToken = 0x600013c] [offset 0x00000043] [找到Native Int] [字节的预期地址]堆栈上的意外类型。

     

[:System.Drawing.BufferedGraphicsContext :: bFillColorTable] [mdToken = 0x600013c] [offset 0x00000027] [找到Native Int] [字节的预期地址]堆栈上的意外类型。

     

[:System.Drawing.Icon :: ToBitmap] [mdToken = 0x6000349] [offset 0x00000084] [找到非托管指针] [预期的非托管指针]堆栈上的意外类型。

     

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

     

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

如果您不打算使用任何这些方法或类型,那么您可能不会遇到任何问题。没有办法将" safe"来自"不安全的东西"项目

另一个内疚关联的例子是:

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,版本= 4.0.0.0,culture = neutral,publickeytoken = b03f5f7f11d50a3a,processorarchitecture = x86。'您正在注册未在SQL Server托管环境中进行全面测试,并且不受支持。将来,如果升级或维护此程序集或.NET Framework,则CLR集成例程可能会停止工作。有关详细信息,请参阅SQL Server联机丛书。

     

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

     

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

     

Msg 6212,Level 16,State 1,Line 1
  CREATE ASSEMBLY失败,因为方法' TypeDescriptorRefreshed' on type' System.Windows.Markup.ValueSerializer'在安全组装和System.Xaml'正在存储到静态字段。安全组件中不允许存储到静态字段。

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

<强> CONLUSION
那么加载UNSAFE .Net Framework程序集是否可以?这真的应该归结为测试。大量测试(不仅仅是开发盒上的单个线程,而是真正的测试)。如果一切都像预期的那样,那么你应该没问题。但是,如果某些内容没有按预期运行,那么是一个可以向Microsoft报告的错误,因为它已经被声明为不受支持。


修改
以下是对此问题的更正式回答,其中列出了可能出现问题的几种情况:Support policy for untested .NET Framework assemblies in the SQL Server CLR-hosted environment