【问题标题】:Is it ok to load .net dlls into SQL Server as UNSAFE?可以将 .net dll 作为 UNSAFE 加载到 SQL Server 中吗?
【发布时间】:2010-10-20 18:29:49
【问题描述】:

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

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

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

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

非常感谢。

【问题讨论】:

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


    【解决方案1】:

    这个问题专门针对加载不在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.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.Web 加载为SAFE 并将System.Xaml 加载为UNSAFE?可能是因为SAFE 程序集中的代码不允许调用UNSAFE 程序集中的代码(至少不能在SQLCLR 中)。

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


    编辑:
    下面是对这个问题的更官方的回答,其中列出了可能出现问题的几种情况:Support policy for untested .NET Framework assemblies in the SQL Server CLR-hosted environment

    【讨论】:

      【解决方案2】:

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

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

      希望对你有帮助

      【讨论】:

        【解决方案3】:

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

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

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

        【讨论】:

        • 好的。 SQL Server 不区分重新启动服务器或使用 P/Invoke。
        猜你喜欢
        • 2011-03-29
        • 2023-03-29
        • 2016-02-27
        • 1970-01-01
        • 1970-01-01
        • 2022-10-17
        • 2011-06-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多