Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Sicurezza rigorosa CLR su SQL Server 2017

In che modo un assembly CLR creato con PERMISSION_SET =SAFE può essere in grado di accedere a risorse di sistema esterne, chiamare codice non gestito e acquisire privilegi di amministratore di sistema?

Ciò è dovuto alle modifiche alla sicurezza apportate in .NET Framework, a partire dalla versione 4.5 (credo).

La documentazione MSDN per Nozioni di base sulla protezione dall'accesso di codice indica:

Il .NET Framework fornisce un meccanismo per l'imposizione di vari livelli di attendibilità su codice diverso in esecuzione nella stessa applicazione chiamato Code Access Security (CAS). Code Access Security in .NET Framework non deve essere utilizzato come meccanismo per imporre limiti di sicurezza in base all'origine del codice o ad altri aspetti dell'identità. Stiamo aggiornando la nostra guida per riflettere che la sicurezza dell'accesso al codice e il codice di sicurezza trasparente non saranno supportati come confine di sicurezza con codice parzialmente attendibile, in particolare codice di origine sconosciuta. Sconsigliamo di caricare ed eseguire codice di origine sconosciuta senza mettere in atto misure di sicurezza alternative.

Quindi punta alla pagina per Modifiche alla sicurezza in .NET Framework che afferma:

La modifica più importante alla sicurezza in .NET Framework 4.5 è nella denominazione forte.

Che poi punta alla documentazione per Enhanced Strong Naming che afferma:

Le chiavi del nome sicuro sono costituite da una chiave di firma e una chiave di identità. L'assembly è firmato con la chiave di firma ed è identificato dalla chiave di identità. Prima di .NET Framework 4.5, queste due chiavi erano identiche. A partire da .NET Framework 4,5, la chiave di identità rimane la stessa delle versioni precedenti di .NET Framework, ma la chiave di firma è migliorata con un algoritmo hash più potente. Inoltre, la chiave di firma viene firmata con la chiave di identità per creare una controfirma.

INOLTRE, la documentazione per le Linee guida per la codifica sicura afferma:

Code Access Security e Security-Transparent Code non saranno supportati come limite di sicurezza con codice parzialmente attendibile. Sconsigliamo di caricare ed eseguire codice di origine sconosciuta senza mettere in atto misure di sicurezza alternative...

Pertanto, il modello di sicurezza per .NET è cambiato anni fa, ma a SQL Server (fino a SQL Server 2017) è stato consentito di continuare a utilizzare il vecchio modello di sicurezza. Sembra che, a partire da SQL Server 2017, sia stata presa la decisione di non supportare più il vecchio modello di sicurezza.

Sospetto che consentire il vecchio modello di sicurezza fosse:

  • impedire che SQL Server (almeno la funzionalità/i componenti relativi a CLR) sia basato sulle versioni più recenti di .NET Framework e

  • responsabile della rimozione improvvisa di SQLCLR come funzionalità supportata dal database SQL di Azure (il supporto era stato aggiunto alla fine del 2014 con il lancio della v12, ma poi rimosso del tutto a partire dal 15 aprile 2016).

Quindi, sì, questo fa schifo. Ciò che significa (almeno per il momento) è che bisogna prima crea un certificato o una chiave asimmetrica (che è stata utilizzata per firmare eventuali Assemblee da caricare) in [master] per quindi creare un accesso da e quindi concedere UNSAFE ASSEMBLY a quel Login. Questa è la stessa sequenza di eventi che è necessario eseguire durante il caricamento di EXTERNAL_ACCESS e UNSAFE Gli assemblaggi, ma ora, sfortunatamente, devono essere fatti anche per SAFE Assemblee.

Attualmente non esiste alcun meccanismo per gestirlo in modo completamente portatile (ovvero non fare affidamento su file esterni) e non può essere gestito da Visual Studio/SSDT senza intervento manuale. Questo era già un po' il caso, ma almeno era possibile creare una configurazione per gestirlo in modo completamente portatile (cioè interamente contenuto all'interno di uno script .sql):per favore vedere Stairway to SQLCLR Level 7:Development and Security per i dettagli (questo è un articolo che ho scritto).

È possibile creare un certificato da byte esadecimali (es. FROM BINARY = 0x... ) ma non funziona con Visual Studio (che si basa su MSBuild) / SSDT poiché l'utilizzo del certificato richiede l'uso di signtool e MSBuild usa sn .

Affinché ciò sia reso praticabile in modo tale che il processo di pubblicazione di Visual Studio / MSBuild / SSDT funzioni (il che a sua volta significherebbe che chiunque sarebbe in grado di creare uno script .sql completamente autonomo in grado di creare la chiave asimmetrica senza fare affidamento su un file esterno), il CREATE ASYMMETRIC KEY il comando deve essere migliorato per consentire la creazione da una stringa binaria. Ho dato questo suggerimento su Microsoft Connect – Consenti la creazione di una chiave asimmetrica da una stringa di byte esadecimali binari proprio come CREATE CERTIFICATE – quindi per favore supportalo :-).

In alternativa (per il momento, fino a quando si spera che MS non crei un metodo migliore, come i miei suggerimenti sulla chiave asimmetrica), puoi provare una delle due tecniche che descrivo nei seguenti post del blog (entrambe funzionano completamente con SSDT):

  • SQLCLR e SQL Server 2017, parte 2:"Sicurezza rigorosa CLR" – Soluzione 1
  • SQLCLR rispetto a SQL Server 2017, parte 3:"Sicurezza rigorosa CLR" – Soluzione 2

Come ultimo resort, puoi considerare il seguente approccio:

  1. TEMPORANEAMENTE imposta il [master] Database su TRUSTWORTHY ON

    Per il passaggio successivo (ad esempio CREATE ASSEMBLY ) per essere eseguito correttamente, il Login che è il proprietario del database (ovvero lo stesso SID utilizzato da [dbo] Utente di [master] ) deve avere il UNSAFE ASSEMBLY autorizzazione. Se [master] è di proprietà di sa o qualsiasi altro amministratore di sistema, quindi dispone di tutte le autorizzazioni e questo requisito è stato soddisfatto. Ma, se [master] è di proprietà di un login con privilegi bassi (una "migliore pratica"), sarà necessario eseguire la seguente istruzione per CREATE ASSEMBLY per funzionare quando TRUSTWORTHY è ON :

    EXEC (N'USE [master]; GRANT UNSAFE ASSEMBLY TO [{DB_Owner_Login}];');
    
  2. Crea l'Assemblea in [master]
  3. Crea la chiave asimmetrica dall'assieme
  4. Lascia l'Assemblea
  5. imposta il [master] Database su TRUSTWORTHY OFF
  6. Crea il Login dalla Chiave Asimmetrica
  7. Concedi UNSAFE ASSEMBLY a quel Login (questo sostituisce la necessità che il DB in cui è caricato l'Assembly sia impostato su TRUSTWORTHY ON e per il suo proprietario Accedi per avere il UNSAFE ASSEMBLY permesso).

Tieni presente che non includere la nuova funzione "Assemblaggio attendibile" come opzione qui. Il motivo per cui non è stato menzionato è dovuto al fatto che presenta molti più difetti che vantaggi, per non parlare del fatto che in primo luogo è del tutto superfluo dato che le funzionalità esistenti hanno già gestito la situazione "Trusted Assemblies" doveva affrontare. Per i dettagli completi su questo e una demo del modo corretto di gestire gli assembly esistenti e non firmati, vedere:SQLCLR vs. SQL Server 2017, parte 4:"Trusted Assemblies" - La delusione.