Hvordan kan en CLR-assembly oprettet med PERMISSION_SET =SAFE muligvis få adgang til eksterne systemressourcer, kalde ikke-administreret kode og erhverve sysadmin-rettigheder?
Dette skyldes sikkerhedsændringer foretaget i .NET Framework, der starter i version 4.5 (tror jeg).
MSDN-dokumentation til Code Access Security Basics siger:
.NET Framework giver en mekanisme til håndhævelse af forskellige niveauer af tillid på forskellig kode, der kører i den samme applikation kaldet Code Access Security (CAS). Code Access Security i .NET Framework bør ikke bruges som en mekanisme til at håndhæve sikkerhedsgrænser baseret på kodeoprindelse eller andre identitetsaspekter. Vi opdaterer vores vejledning for at afspejle, at kodeadgangssikkerhed og sikkerhedsgennemsigtig kode ikke vil blive understøttet som en sikkerhedsgrænse med delvist betroet kode, især kode af ukendt oprindelse. Vi fraråder at indlæse og udføre kode af ukendt oprindelse uden at indføre alternative sikkerhedsforanstaltninger.
Og peger derefter på siden for sikkerhedsændringer i .NET Framework, hvor der står:
Den vigtigste ændring af sikkerheden i .NET Framework 4.5 er i stærk navngivning.
Hvilket så peger på dokumentationen for Enhanced Strong Naming, hvor der står:
Stærke navnenøgler består af en signaturnøgle og en identitetsnøgle. Samlingen er signeret med signaturnøglen og identificeres med identitetsnøglen. Før .NET Framework 4.5 var disse to nøgler identiske. Fra og med .NET Framework 4.5 forbliver identitetsnøglen den samme som i tidligere .NET Framework-versioner, men signaturnøglen er forbedret med en stærkere hash-algoritme. Derudover er signaturnøglen signeret med identitetsnøglen for at skabe en modsignatur.
OGSÅ står der i dokumentationen til Secure Coding Guidelines:
Kodeadgangssikkerhed og sikkerhedsgennemsigtig kode vil ikke blive understøttet som en sikkerhedsgrænse med delvist betroet kode. Vi fraråder at indlæse og udføre kode af ukendt oprindelse uden at indføre alternative sikkerhedsforanstaltninger...
Så sikkerhedsmodellen for .NET ændrede sig for år siden, men SQL Server (indtil SQL Server 2017) har fået lov til at fortsætte med at bruge den gamle sikkerhedsmodel. Det ser ud til, at der fra og med SQL Server 2017 blev besluttet ikke længere at understøtte den gamle sikkerhedsmodel.
Jeg formoder, at det at tillade den gamle sikkerhedsmodel var:
-
forhindrer SQL Server (i det mindste den CLR-relaterede funktionalitet/komponenter) i at være baseret på de nyere .NET Framework-versioner, og
-
ansvarlig for den bratte fjernelse af SQLCLR som en understøttet funktion fra Azure SQL Database (understøttelse var blevet tilføjet i slutningen af 2014 med lanceringen af v12, men blev derefter fjernet helt fra den 15. april 2016).
Så ja, det er noget ærgerligt. Hvad det betyder (i hvert fald for øjeblikket) er, at man skal først opret et certifikat eller en asymmetrisk nøgle (som er blevet brugt til at signere alle samlinger, der skal indlæses) i [master]
for derefter at oprette et login fra og derefter give UNSAFE ASSEMBLY
til det login. Dette er den samme sekvens af hændelser, som man skal gøre, når man indlæser EXTERNAL_ACCESS
og UNSAFE
Monteringer, men nu skal de desværre gøres for selv at være SAFE
Forsamlinger.
Der er i øjeblikket ingen mekanisme til at håndtere dette på en fuldstændig bærbar måde (dvs. ikke stole på eksterne filer) og kan ikke håndteres af Visual Studio / SSDT uden manuel indgriben. Dette var sådan set allerede tilfældet, men det var i det mindste muligt at oprette et setup til at håndtere dette på en fuldstændig bærbar måde (dvs. helt indeholdt i et .sql-script):se venligst Stairway to SQLCLR Level 7:Development and Security for detaljer (dette er en artikel, jeg skrev).
Det er muligt at oprette et certifikat fra hex bytes (dvs. FROM BINARY = 0x...
), men det virker ikke med Visual Studio (som er afhængig af MSBuild) / SSDT, da brug af certifikatet kræver brug af signtool
og MSBuild bruger sn
.
For at dette kan gøres brugbart, således at Visual Studio/MSBuild/SSDT-udgivelsesprocessen fungerer (hvilket igen ville betyde, at enhver ville være i stand til at skabe et fuldstændig selvstændigt .sql-script, der er i stand til at skabe den asymmetriske nøgle uden at stole på en ekstern fil), CREATE ASYMMETRIC KEY
kommandoen skal forbedres for at tillade oprettelse fra en binær streng. Jeg har fremsat dette forslag om Microsoft Connect – Tillad, at asymmetrisk nøgle oprettes ud fra binære hex-bytes-strenge ligesom CREATE CERTIFICATE – så støtte det venligst :-).
Alternativt (i øjeblikket, indtil MS forhåbentlig skaber en bedre metode, såsom mine forslag til asymmetriske nøgler), kan du prøve en af de to teknikker, jeg beskriver i følgende blogindlæg (begge fungerer fuldt ud med SSDT):
- SQLCLR vs. SQL Server 2017, del 2:"CLR strict security" – Løsning 1
- SQLCLR vs. SQL Server 2017, del 3:"CLR strict security" – Løsning 2
Som en sidste udvej, kan du overveje følgende fremgangsmåde:
-
MIDLERTIDIG indstil
[master]
Database tilTRUSTWORTHY ON
Til næste trin (dvs.
CREATE ASSEMBLY
) for at udføre succesfuldt, login, der er databaseejeren (dvs. samme SID, der bruges af[dbo]
Bruger af[master]
) skal have denUNSAFE ASSEMBLY
tilladelse. Hvis[master]
ejes afsa
eller enhver anden sysadmin, så har den alle tilladelser, og dette krav er blevet opfyldt. Men hvis[master]
ejes af et lavprivilegeret login (en "best practice"), så skal du udføre følgende sætning for atCREATE ASSEMBLY
til at fungere, nårTRUSTWORTHY
erON
:EXEC (N'USE [master]; GRANT UNSAFE ASSEMBLY TO [{DB_Owner_Login}];');
- Opret samlingen i
[master]
- Opret den asymmetriske nøgle fra samlingen
- Slip forsamlingen
- indstil
[master]
Database tilTRUSTWORTHY OFF
- Opret login fra den asymmetriske nøgle
- Giv
UNSAFE ASSEMBLY
til det pågældende login (dette erstatter behovet for, at DB'en, hvor forsamlingen er indlæst, skal indstilles tilTRUSTWORTHY ON
og for dens ejer Log ind for at have denUNSAFE ASSEMBLY
tilladelse).
Bemærk venligst, at jeg ikke gjorde det inkludere den nye "Trusted Assembly"-funktion som en mulighed her. Grunden til, at det ikke blev nævnt, skyldes, at det har mange flere fejl end fordele, for ikke at nævne, at det i første omgang er helt unødvendigt, da eksisterende funktionalitet allerede håndterede situationen, "Trusted Assemblys" skulle løse. For alle detaljer om det og en demo af den korrekte måde at håndtere eksisterende, usignerede samlinger, se venligst:SQLCLR vs. SQL Server 2017, del 4:"Trusted Assemblys" – The Disappointment.