Security implications of enabling CLR on shared instance

Posted on

Question :

My database is currently isolated in its own instance and VM. My customer is retiring that server and I need to migrate the DB to a new environment. My DB uses CLR, so the new environment needs to have that enabled.

The customer proposed using an existing server with an existing SQLServer 2014 Standard instance hosting DBs from other software vendors on it. I’m concerned about incurring a sort of “you break it, you bought it” liability, since I can’t vouch for the security strategy of those other DBs or their front-ends. I don’t want to do something that would introduce a significant risk.

I run into similar scenarios with other customers from time to time. I’m a database developer. I occasionally provide DBA services pertaining to my own product for my small to medium business customers, but I am by no means a skilled DBA. Each customer has different budgets, priorities, IT staff, and security policies, but generally none of them have IT/DBAs that can understand and/or make competent risk assessments at this level of detail.

How would enabling CLR on a shared instance affect the security of the other DBs? (I am not asking about database-level permission_set levels, just enabling CLR itself). I need to understand the risk (if there is any) well enough to be able to advise a ‘best practice’ and a customer-specific ‘secure enough’ alternative.

Answer :

Given that we are dealing with a shared instance, it should be safe to assume that none of the logins for the “customer” DBs has sysadmin privileges or has been granted the CONTROL SERVER permission.

Under such conditions, there should not be any security risk to having SQLCLR enabled, regardless of what many people seem to claim. Having the instance-level “CLR enabled” option enabled merely allows for a login that has the appropriate permission to load assemblies, and for loaded assemblies to be used by anyone granted access to the objects in those assemblies.

If users cannot load assemblies, then there can be no risk of having unknown code in assemblies, because there won’t be any assemblies. Then, if one user (such as yourself) is granted the CREATE ASSEMBLY permission (which should be coupled with using Certificates to handle the assembly security), then only you can load assemblies.

Of course, for SQL Server 2005 – 2016, and for SQL Server 2017 and newer that has the “CLR strict security” instance-level configuration option disabled, the database owner (i.e. the dbo user) and any user in the db_owner fixed database role can create SAFE assemblies, but those aren’t a security risk. Sure, they might be a performance risk, but the same is true for sloppy data modeling, T-SQL, triggers, etc. If the various vendors are not dbo for their databases, then this is a non-issue. If the vendors are dbo for their respective databases and the desire is to prevent them creating SAFE assemblies, it is easy enough to create an instance-wide DDL trigger for the CREATE ASSEMBLY statement and issue a ROLLBACK if the user is not you and/or it is not executed within your database.

If someone is a member of the sysadmin instance-level role, or granted the CONTROL SERVER instance-level permission, then they can also load assemblies. BUT, and here is what most “security” related recommendations miss: having “CLR enabled” disabled does not protect against someone who is a sysadmin or has CONTROL SERVER permission because they have permission to enable the “CLR enabled” option (and enable xp_cmdshell, etc and do whatever they want)!

There is no inherent risk in having this option enabled because having it enabled does not give anyone the permission to load assemblies that pose a security risk (in SQL Server 2005 – 2016, dbo and users in db_owner role can load SAFE assemblies). And, once loaded, assemblies marked as EXTERNAL_ACCESS or UNSAFE need additional security (i.e. Certificates / strong naming, not TRUSTWORTHY) in order for their code to be executed. And, starting in SQL Server 2017 all assemblies, by default, need that additional security just to be loaded in the first place. And, that additional security (for the operation of the assembly) requires sysadmin level permissions:

  • In the unfortunate case of someone setting the database to TRUSTWORTHY ON, the login that owns the DB needs to have either the EXTERNAL ACCESS ASSEMBLY or UNSAFE ASSEMBLY permission (for SQL Server 2017+ with “CLR strict security” enabled — the default — it must be UNSAFE ASSEMBLY), which can only be granted by a sysadmin (these permissions are obviously implied if the owning login is a sysadmin). Hopefully vendor DBs would never have TRUSTWORTHY enabled.
  • When assemblies are signed, a certificate or asymmetric key needs to be created in the [master] DB, then a login needs to be created from that, then that login needs to be granted either the EXTERNAL ACCESS ASSEMBLY or UNSAFE ASSEMBLY permission (for SQL Server 2017+ with “CLR strict security” enabled — the default — it must be UNSAFE ASSEMBLY).

For some examples of handling SQLCLR security, please see:

That being said, as David Browne noted in a comment on this answer:

Another important point is about the trust that presumably exists among the stakeholders for the various databases. In a corporate environment, everyone is expected to be trustworthy and cooperative. in a 3rd party hosting environment, you have to assume that the owner of the adjacent workload is a completely untrusted and even malicious actor. Lots of not-perfectly-safe things are safe-enough to do behind a firewall and among friends.

Leave a Reply

Your email address will not be published. Required fields are marked *