使用 SQL CLR 的安全或性能风险

SQL*_*Ben 11 performance security sql-server sql-clr

在 SQL Server 中使用 CLR 是否存在任何特定的安全或性能风险?

Sol*_*zky 10

正如 Remus 所指出的,这个问题过于笼统,无法得到答案,因为答案取决于要使用什么功能以及如何使用的上下文。

关于“安全”:

如果您询问可以在标有 的程序集中完成的任何事情PERMISSION_SET = SAFE,那么我找不到任何问题。并且 SQLCLR 比使用xp_cmdshell或美妙的(那是讽刺)sp_OA*过程(甚至扩展存储过程,但希望没有人再创建任何这些过程)“更安全” 。

如果您想了解“SAFE”在实际中的含义,请参阅这篇文章:通往 SQLCLR 级别 3 的阶梯:安全性(常规和安全程序集)(需要免费注册)。

如果您询问在标有 的程序集中可以完成的任何事情PERMISSION_SET = EXTERNAL_ACCESS,那么肯定存在风险,同样,这取决于所使用的功能。如果您编写一个例程来读取目录和文件名(即只读),那么这只是应该看到和不看到的问题。如果您正在编写允许删除文件的代码,则风险会增加。但是可以用这些外部资源做什么是由以下控制的:

  • 无论您是否使用模拟:
    • 无模拟意味着通过 SQL Server 服务的“登录身份”帐户访问外部资源。无论该帐户有权访问什么,您的 SQLCLR 函数都可以做到。
    • 使用模拟意味着运行该函数的 SQL Server 中的登录名(如果该登录名对应于 Windows 登录名)可以执行允许该特定 Windows 登录名执行的任何操作。如果 SQL Server 中的登录名是 SQL Server 登录名,则尝试使用模拟会出错。
  • 在外部资源上设置了哪些权限。对于文件系统访问,这是通过 NTFS 驱动器上的 ACL 控制的。

如果您询问可以在标记为的程序集中完成的任何事情 PERMISSION_SET = UNSAFE,这是相当开放的。许多功能被认为只能在 UNSAFE 程序集中使用,因为它们是稳定性和/或一致行为的问题,而不是安全或性能问题。例如,在 UNSAFE 程序集中,可能有一个可写的静态变量。这通常不是一件好事,因为 SQLCLR 类在所有会话之间共享。如果您的意图是在所有会话中共享内存中的数据,并且已经为竞争条件做好了计划(并进行了大量测试),那么您应该没问题,因为您期望这种行为。但是,如果您只是想要一个可写的静态变量来缓存特定会话的值,而不必再次查找或再次计算它,并且不知道其他会话正在读取该值并可能覆盖它,那么,那将是一个问题。

但是,如果您担心有人写入注册表,但没有任何实际写入注册表的代码,那么您可能不需要担心这个;-)。

如果您想了解 EXTERNAL_ACCESS 和 UNSAFE 在实际中是如何工作的,以及设置TRUSTWORTHY ON(非首选)与使用基于非对称密钥或基于证书的登录之间的区别,请参阅这篇文章:通往 SQLCLR 级别 4 的阶梯:安全(外部和不安全组件)(需要免费注册)。

关于“性能”:

这完全取决于您正在尝试做什么以及您如何去做。有一些事情是很多的SQLCLR更快,有些事情是要慢。但就像使用 T-SQL 一样,有可能执行一些简单和/或高效的任务,并通过做不正确的事情使其复杂和/或低效。但是使用 SQL CLR 从本质上来说并不是更慢。


Rem*_*anu 6

SQLCLR 程序集可以通过三个级别的安全访问进行安装:SAFE | EXTERNAL_ACCESS | UNSAFE. 这有充分的记录,请参阅CREATE ASSEMBLY设计组件

管理程序集安全性
您可以控制程序集在运行托管代码时可以访问受 .NET 代码访问安全性保护的资源的数量。您可以通过在创建或修改程序集时指定三个权限集之一来执行此操作:SAFE、EXTERNAL_ACCESS 或 UNSAFE。

SAFE
SAFE 是默认权限集,它是最严格的。由具有 SAFE 权限的程序集运行的代码无法访问外部系统资源,例如文件、网络、环境变量或注册表。SAFE 代码可以访问本地 SQL Server 数据库中的数据,或者执行不涉及访问本地数据库外部资源的计算和业务逻辑。
大多数程序集执行计算和数据管理任务而无需访问 SQL Server 外部的资源。因此,我们推荐 SAFE 作为程序集权限集。

EXTERNAL_ACCESS
EXTERNAL_ACCESS 允许程序集访问某些外部系统资源,例如文件、网络、Web 服务、环境变量和注册表。只有具有 EXTERNAL ACCESS 权限的 SQL Server 登录名才能创建 EXTERNAL_ACCESS 程序集。SAFE 和 EXTERNAL_ACCESS 程序集只能包含可验证类型安全的代码。这意味着这些程序集只能通过对类型定义有效的明确定义的入口点访问类。因此,他们不能随意访问不属于代码的内存缓冲区。此外,它们无法执行可能对 SQL Server 进程的稳健性产生不利影响的操作。

UNSAFE
UNSAFE 使程序集可以不受限制地访问 SQL Server 内部和外部的资源。在 UNSAFE 程序集中运行的代码可以调用非托管代码。此外,指定 UNSAFE 允许程序集中的代码执行 CLR 验证程序认为类型不安全的操作。这些操作可能会以不受控制的方式访问 SQL Server 进程空间中的内存缓冲区。UNSAFE 程序集还可能破坏 SQL Server 或公共语言运行时的安全系统。UNSAFE 权限应仅由经验丰富的开发人员或管理员授予高度信任的程序集。只有 sysadmin 固定服务器角色的成员才能创建 UNSAFE 程序集。

对允许的 CLR 属性有进一步的限制,并且仅支持 .Net Framework 程序集的一个子集。同样,请参阅链接的文档。

至于性能,最重要的想法是记住 SQL Server 是一个协作的多任务环境,而 CLR 不是。SQLCLR 代码必须Thread.BeginThreadAffinity()在任何持续时间(包括阻塞)占用 CPU 的任何时间调用。Adam Machanic 有一个关于这个主题的精彩演讲,观看数据,更快:Microsoft SQL Server Performance Techniques with SQLCLR

话题很广,问题也很模糊。SQLCLR 可以执行一些其他功能无法比拟的独特任务。而 SQLCLR 只是 SQL Server 武器库中的另一种武器,您可以用性能或安全性来打击自己。阅读文档。