是否可以将 .net dll 以不安全的方式加载到 SQL Server 中?

发布于 2024-07-17 16:20:39 字数 344 浏览 4 评论 0原文

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

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

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

是否可以将 .net 框架加载为 UNSAFE 而不确切地知道它正在做什么? 这样做会如何损害 sql server 的安全性/稳健性/可扩展性(正如微软警告的那样)?

非常感谢。

When creating a SQL Server CLR stored procedure, I noticed that I couldn't reference anything in the .net framework as I would normally. After some reading around, I realised that assemblies needed to be loaded into the database first.

Therefore, I loaded in the ones I need but due to P/Invoke had to use the UNSAFE permission set. I can now reference them in my stored procedure code and everything works fine.

However, I'm a little concerned about having to set them to UNSAFE when I don't really know what they are doing. So my question is this:

Is it ok to load the .net framework in as UNSAFE without exactly what it's doing?
And how would doing so compromise security/robustness/scalability of sql server (as microsoft warn it could)?

Many thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

捂风挽笑 2024-07-24 16:20:39

它可以更改注册表、重新启动服务、重新启动服务器等。没什么太重要的;-)一个简单的 差异图表

也请参阅此问题(尽管没有答案)SQL Server 2008:加载非托管库的 CLR 存储过程的崩溃安全性如何

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

It could change the registry, restart services, reboot the server etc. Nothing too important ;-) A simple chart with the differences

See this question too (no answers though) SQL Server 2008: How crash-safe is a CLR Stored Procedure that loads unmanaged libraries

Of course, what are you doing that requires UNSAFE access?

佼人 2024-07-24 16:20:39

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

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

希望能帮助到你

When you use the SQL database engine on a server which is hosting many many public websites you don't know anything about as a server administrator (or DBA or whoever responsible), you should restrict their access and damn it's important! Also if you have a DBA in a restricted area, where data matters the most in some big companies, again it's the most important thing.

In my point of view, you should give your application as it needs to see, nothing more. If you don't need to see the registry for example, why you wanna give unrestricted access to the assembly? You have no idea how dangerous it could be if somebody injects the code of your application and hijack into the database (also with an unrestricted access!).

Hope it helps

夜未央樱花落 2024-07-24 16:20:39

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

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

某些不在受支持列表中的 .Net Framework 程序集可以通过设置为 SAFEPERMISSION_SET 进行加载。 然而,这并不能保证期望的行为。 有些可以作为 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][偏移量 0x00000053][找到的字节地址]堆栈上预期的数字类型。

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

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

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

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

[ : System.Drawing.Icon::GetShort][mdToken=0x6000356][偏移量 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.Web 加载为 SAFE 并将 System.Xaml 加载为 UNSAFE 呢? 可能是因为 SAFE 程序集中的代码不允许调用 UNSAFE 程序集中的代码(至少在 SQLCLR 中不允许)。

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


编辑:
以下是对此问题的更官方答案,其中列出了可能发生问题的几种情况:对 SQL Server CLR 托管环境中未经测试的 .NET Framework 程序集的支持策略

This question is specific to loading .Net Framework assemblies that are not in the set of Supported .NET Framework Libraries, so I will focus on the context being Microsoft supplied DLLs rather than any random DLL.

The difference between the assemblies in the "Supported" list and those not in the list comes down to the fact that the supported ones "have been tested to ensure that they meet reliability and security standards for interaction with SQL Server" (as noted in the "Supported Libraries" page linked above). The main issue is more so the "reliability" than the "security". The assemblies in the supported list have been verified to behave consistently as expected and without any bugs or odd side-effects. The functionality has been tested to work with various languages and collations, etc.

Some .Net Framework assemblies that are not in the supported list can be loaded with a PERMISSION_SET set to SAFE. This, however, does not guarantee desired behavior. And some can be loaded as UNSAFE without necessarily indicating that there will be a problem.

As an example of not guaranteeing behavior: I have loaded System.Drawing in order to do some simple image manipulation. I tested manipulations when the image was supplied directly via byte[] / VARBINARY(MAX) as well as when it was supplied by a filepath and read from disk. Everything worked as expected. I sent that to someone in Germany whose Windows and SQL Server were both set to "German" as the language. He was able to get the expected results when supplying the image directly. But when he supplied a filepath it didn't work.

And regarding undesired behavior, SQL Server will display the reasons why the assembly can't load as either SAFE or EXTERNAL_ACCESS when you try to do it. For example:

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

Results in:

Warning: The Microsoft .NET Framework assembly 'system.drawing, version=4.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a, processorarchitecture=msil.' you are registering is not fully tested in the SQL Server hosted environment and is not supported. In the future, if you upgrade or service this assembly or the .NET Framework, your CLR integration routine may stop working. Please refer SQL Server Books Online for more details.

Msg 6218, Level 16, State 2, Line 1
CREATE ASSEMBLY for assembly 'System.Drawing' failed because assembly 'System.Drawing' failed verification. Check if the referenced assemblies are up-to-date and trusted (for external_access or unsafe) to execute in the database. CLR Verifier error messages if any will follow this message

[ : System.Drawing.BufferedGraphicsContext::bFillColorTable][mdToken=0x600013c][offset 0x00000053][found address of Byte] Expected numeric type on the stack.

[ : System.Drawing.BufferedGraphicsContext::bFillColorTable][mdToken=0x600013c][offset 0x00000043][found Native Int][expected address of Byte] Unexpected type on the stack.

[ : System.Drawing.BufferedGraphicsContext::bFillColorTable][mdToken=0x600013c][offset 0x00000027][found Native Int][expected address of Byte] Unexpected type on the stack.

[ : System.Drawing.Icon::ToBitmap][mdToken=0x6000349][offset 0x00000084][found unmanaged pointer][expected unmanaged pointer] Unexpected type on the stack.

[ : System.Drawing.Icon::ToBitmap][mdToken=0x6000349][offset 0x000000E4] Unmanaged pointers are not a verifiable type.

[ : System.Drawing.Icon::GetShort][mdToken=0x6000356][offset 0x00000002] Unmanaged pointers are not a verifiable type.
...

If you are not going to use any of those methods or types, then you likely will not have any issues. There is just no way to separate out the "safe" stuff from the "unsafe" items.

Another example of guilt-by-association, but even farther removed, is:

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

Results in:

Warning: The Microsoft .NET Framework assembly 'system.web, version=4.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a, processorarchitecture=x86.' you are registering is not fully tested in the SQL Server hosted environment and is not supported. In the future, if you upgrade or service this assembly or the .NET Framework, your CLR integration routine may stop working. Please refer SQL Server Books Online for more details.

Warning: The Microsoft .NET Framework assembly 'microsoft.build.framework, version=4.0.0.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a, processorarchitecture=msil.' you are registering is not fully tested in the SQL Server hosted environment and is not supported. In the future, if you upgrade or service this assembly or the .NET Framework, your CLR integration routine may stop working. Please refer SQL Server Books Online for more details.

Warning: The Microsoft .NET Framework assembly 'system.xaml, version=4.0.0.0, culture=neutral, publickeytoken=b77a5c561934e089, processorarchitecture=msil.' you are registering is not fully tested in the SQL Server hosted environment and is not supported. In the future, if you upgrade or service this assembly or the .NET Framework, your CLR integration routine may stop working. Please refer SQL Server Books Online for more details.

Msg 6212, Level 16, State 1, Line 1
CREATE ASSEMBLY failed because method 'TypeDescriptorRefreshed' on type 'System.Windows.Markup.ValueSerializer' in safe assembly 'System.Xaml' is storing to a static field. Storing to a static field is not allowed in safe assemblies.

As you can see, System.Web is actually, by itself, fine for SAFE, but it has dependent assemblies and those are being auto-loaded. The first dependent assembly, microsoft.build.framework also has no issues (at least not that can be verified, though it is possible that something that is disallowed in SAFE is there but can only be caught at run-time). But the second dependent assembly does have an issue that can be verified upon loading the assembly: it is "storing to a static field". This is a problem for reliability more than security because classes are instantiated one time (well, per App Domain, meaning: per-database, per owner) and shared across the SPIDs to use (which is why only static methods are accessible in SQLCLR). Hence, static class-level variables are technically sharing information between sessions (i.e. SPIDs) and that can very easily cause unexpected behavior. But at the same time, if you only want to use HtmlString.ToHtmlString(), then you probably aren't making use of System.Xaml. So why doesn't it just load System.Web as SAFE and System.Xaml as UNSAFE? Probably because code in SAFE assemblies is not allowed to call code in UNSAFE assemblies (at least not in SQLCLR).

CONLUSION
So is it OK to load UNSAFE .Net Framework assemblies? That really should come down to testing. Lots of testing (and not just a single thread on your dev box, but real testing). If everything behaves as expected then you should be fine. But, if something does not behave as expected, then it is not a bug that can be reported to Microsoft because it has already been declared as unsupported.


EDIT:
And here is a more official answer to this question, which lists a few situations where problems could occurr: Support policy for untested .NET Framework assemblies in the SQL Server CLR-hosted environment

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文