Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Segurança Estrita CLR no SQL Server 2017


Como um assembly CLR criado com PERMISSION_SET =SAFE pode acessar recursos externos do sistema, chamar código não gerenciado e adquirir privilégios de administrador de sistema?

Isso se deve às mudanças de segurança feitas no .NET Framework, a partir da versão 4.5 (acredito).

A documentação do MSDN para Noções básicas de segurança de acesso ao código afirma:

O .NET Framework fornece um mecanismo para a imposição de vários níveis de confiança em diferentes códigos executados no mesmo aplicativo chamado Code Access Security (CAS). A Segurança de Acesso ao Código no .NET Framework não deve ser usada como um mecanismo para impor limites de segurança com base na origem do código ou em outros aspectos de identidade. Estamos atualizando nossas orientações para refletir que a Segurança de Acesso ao Código e o Código Transparente à Segurança não serão suportados como um limite de segurança com código parcialmente confiável, especialmente código de origem desconhecida. Desaconselhamos carregar e executar códigos de origens desconhecidas sem implementar medidas de segurança alternativas.

E, em seguida, aponta para a página de alterações de segurança no .NET Framework que afirma:

A mudança mais importante na segurança no .NET Framework 4.5 está na nomenclatura forte.

O que aponta para a documentação do Enhanced Strong Naming, que afirma:

As chaves de nome forte consistem em uma chave de assinatura e uma chave de identidade. O assembly é assinado com a chave de assinatura e é identificado pela chave de identidade. Antes do .NET Framework 4.5, essas duas chaves eram idênticas. A partir do .NET Framework 4.5, a chave de identidade permanece a mesma das versões anteriores do .NET Framework, mas a chave de assinatura é aprimorada com um algoritmo de hash mais forte. Além disso, a chave de assinatura é assinada com a chave de identidade para criar uma contra-assinatura.

ALÉM DISSO, a documentação das Diretrizes de Codificação Segura afirma:

A segurança de acesso ao código e o código transparente de segurança não serão suportados como um limite de segurança com código parcialmente confiável. Desaconselhamos carregar e executar códigos de origens desconhecidas sem implementar medidas de segurança alternativas...

Portanto, o modelo de segurança para .NET mudou anos atrás, mas o SQL Server (até o SQL Server 2017) teve permissão para continuar usando o modelo de segurança antigo. Parece que, a partir do SQL Server 2017, foi tomada a decisão de não suportar mais o antigo modelo de segurança.

Suspeito que permitir o antigo modelo de segurança foi:

  • impedir que o SQL Server (pelo menos a funcionalidade/componentes relacionados ao CLR) seja baseado nas versões mais recentes do .NET Framework e

  • responsável pela remoção abrupta do SQLCLR como um recurso com suporte do Banco de Dados SQL do Azure (o suporte foi adicionado no final de 2014 com o lançamento da v12, mas foi totalmente removido em 15 de abril de 2016).

Então, sim, isso é meio chato. O que significa (pelo menos no momento) é que é preciso primeiro crie um Certificado ou Chave Assimétrica (que tenha sido usada para assinar quaisquer Assemblies a serem carregados) em [master] para então criar um Login de e então conceder UNSAFE ASSEMBLY para esse Login. Esta é a mesma sequência de eventos que se precisa fazer ao carregar EXTERNAL_ACCESS e UNSAFE Montagens, mas agora, infelizmente, precisa ser feito até mesmo para SAFE Montagens.

Atualmente, não há mecanismo para lidar com isso de maneira completamente portátil (ou seja, não depende de arquivos externos) e não pode ser tratado pelo Visual Studio / SSDT sem intervenção manual. Isso já era o caso, mas pelo menos foi possível criar uma configuração para lidar com isso de maneira completamente portátil (ou seja, totalmente contido em um script .sql):consulte Stairway to SQLCLR Level 7:Development and Security para obter detalhes (este é um artigo que escrevi).

É possível criar um Certificado a partir de bytes hexadecimais (ou seja, FROM BINARY = 0x... ), mas isso não funciona com o Visual Studio (que depende do MSBuild) / SSDT, pois o uso do certificado requer o uso de signtool e o MSBuild usa sn .

Para que isso seja viável, de modo que o processo de publicação do Visual Studio / MSBuild / SSDT funcione (o que, por sua vez, significaria que qualquer pessoa seria capaz de criar um script .sql completamente autocontido capaz de criar a chave assimétrica sem depender de um arquivo externo), o CREATE ASYMMETRIC KEY O comando precisa ser aprimorado para permitir a criação de uma string binária. Eu fiz esta sugestão no Microsoft Connect – Permitir que a chave assimétrica seja criada a partir de uma string de bytes hexadecimais binários, assim como CREATE CERTIFICATE – então, por favor, apoie-o :-).

Como alternativa (no momento, até que a MS crie um método melhor, como minhas sugestões de chave assimétrica), você pode tentar uma das duas técnicas que descrevo nas seguintes postagens do blog (ambas funcionam totalmente com SSDT):
  • SQLCLR vs. SQL Server 2017, Parte 2:“segurança estrita do CLR” – Solução 1
  • SQLCLR vs. SQL Server 2017, Parte 3:“segurança estrita do CLR” – Solução 2

Como último resort, você pode considerar a seguinte abordagem:

  1. TEMPORARIAMENTE defina o [master] Banco de dados para TRUSTWORTHY ON

    Para a próxima etapa (ou seja, CREATE ASSEMBLY ) para executar com sucesso, o Login que é o proprietário do banco de dados (ou seja, mesmo SID usado pelo [dbo] Usuário de [master] ) precisa ter o UNSAFE ASSEMBLY permissão. Se [master] é propriedade de sa ou qualquer outro administrador de sistema, então ele tem todas as permissões e esse requisito foi atendido. Mas, se [master] é de propriedade de um login com poucos privilégios (uma "prática recomendada"), então você precisará executar a seguinte instrução para que o CREATE ASSEMBLY para funcionar quando TRUSTWORTHY está ON :
    EXEC (N'USE [master]; GRANT UNSAFE ASSEMBLY TO [{DB_Owner_Login}];');
    
  2. Crie o Assembly em [master]
  3. Crie a chave assimétrica a partir da montagem
  4. Solte a montagem
  5. defina o [master] Banco de dados para TRUSTWORTHY OFF
  6. Crie o login a partir da chave assimétrica
  7. Conceder UNSAFE ASSEMBLY para esse Login (isso substitui a necessidade do banco de dados onde o Assembly é carregado ser definido como TRUSTWORTHY ON e para que seu proprietário faça login para ter o UNSAFE ASSEMBLY permissão).

Observe que eu não inclua o novo recurso "Trusted Assembly" como uma opção aqui. A razão pela qual não foi mencionado é devido ao fato de ter muito mais falhas do que benefícios, sem mencionar que é totalmente desnecessário em primeiro lugar, uma vez que a funcionalidade existente já lidava com a situação que "Trusted Assemblies" deveria resolver. Para obter detalhes completos sobre isso e uma demonstração da maneira correta de lidar com Assemblies não assinados existentes, consulte:SQLCLR vs. SQL Server 2017, Parte 4:“Trusted Assemblies” – The Disappointment.