10
1
CAS este un sistem ce permite administratorilor si dezvoltatorilor sa controleze executia aplicatiilor similar cu modul in care controleaza accesul utilizatorilor. La fel ca la Role Based Security, puteti controla / autoriza accesul aplicatiei (printre altele) la:
Sistemul de fisiere Registry Imprimante EventLog-uri 2
Puteti controla si aspecte pe care nu le puteti controla in RBS. Ex: puteti interzice accesul unei aplicatii la internet sau la servere DNS. CAS se aplica numai la aplicatiile managed (ce folosesc .NET framework). Aplicatiile ce sunt supuse verificarilor CAS sunt “partially trusted”. Cele care nu sunt verificate CAS sunt “fully trusted”. 3
Modalitatea prin care CAS identifica assemblyurile (pentru a le acorda apoi permisii) este evidenta (Evidence). Evidenta poate fi locatia unde este stocata o aplicatie, un hash al codului aplicatiei sau semnatura aplicatiei. Aceasta evidenta determina grupul in care face parte aplicatia. Grupurile la randul lor determina setul de permisii pe care il va avea assembly-ul. 4
Evidenta este informatia care identifica un assembly. Aceasta poate sa fie: Directorul assembly-ului Un hash al assembly-ului Publisher: semnatura digitala a publisher-ului. Aceasta identifica in mod unic dezvoltatorul assembly-ului. Site: site-ul de unde s-a copiat aplicatia Strong Name: Un nume cryptographic al aplicatiei care o identifica pe aceasta in mod unic. URL: url-ul de unde a fost copiata aplicatia Zone: Zona in care ruleaza aplicatia: Internet zone sau LocalInternet 5
Permisiile sunt cele care pot restrictiona actiunile unui assembly. Sunt disponibile 19 permisii in .NET framework 2.0. Fiecare permisie are 2 corespondenti in namespace-ul System.Security.Permisions: unul pentru folosirea imperativa si unul pentru cea declarativa. 6
Cele 19 permisii sunt: Directory Services: acces la active directory DNS: acces la cereri DNS Environment Variables: acces la variabilele de mediu (Path, Username, Number_Of_Processors) Event Log: acces la eventlog-uri File Dialog: permite sau interzice unei assembly sa deschida open si save dialog. File IO: restrictioneaza accesul la fisiere si directoare. Isolated Storage File: permite accesul la Isolated Storage 7
Message Queue: permite unui assembly accesul la coada de mesaje. Performance Counter: permite assembly-ului sa citeasca sau sa scrie in un performance counter. Printing: drept de imprimare Reflection: drept de reflexie. Registry: drept de acces la registry Security: ofera acces detaliat la functiile CAS. Pentru a fi executabil un assembly trebuie sa aiba cel putin setarea Enable Assembly Execution. Aceasta permisie controleaza si posibiliatea unui assembly de a executa cod unmanaged sau de a controle thread-uri. 8
Service Controller: drept de acces la serviciile Windows Socket Acces: drept de folosire socket-uri SQL Client: drept de acces la server SQL User Interface: drept de creare si folosire a unui GUI (dreptul aplicatiei de a crea/folosii windows forms si clipboard) Web access: acces la site-uri web. x509 Store: drept de accesare certificate x509 (se pot accesa, sterge si deschide) 9
Un set de permisii este un grup de permisii . Sunt 7 set-uri predefinite:
FullTrust: verificarile CAS nu se executa SkipVerification: Assebly-ul nu este verificat de CAS Execution: Assebly-ul poate rula. Nu are nici o alta permisie. LocalInternet: Assebly-ul poate imprima si accesa eventlog-ul. Nu poate accesa sistemul de fisiere decat prin dialog-uri open si save file. File Dialog, Isolate Storage File, Security, User Interface, Printing, DNS, Reflection, Environment Variables Internet: File Dialog, Isolate Storage File, Security, User Interface, Printing Everything: Se executa verificarile CAS dar assembly-ul le trece pe toate. 10
Code Group-urile asociaza assembly-uri cu seturi de permisii. Un Code Group este similar cu un user group din RBS. Ex: orice cod vine din internet ar trebuii sa fie membru in grupul Internet_Zone. Un assembly poate fi membru de la mai multe code group-uri. Un grup poate fi membru la alt grup. Grupurile predefinite sunt: My_Computer_Zone: Zone: My Computer, Permission Set: Full Trust LocalIntranet_Zone: Zone: LocalIntranet, Permission Set: LocalIntranet Internet_Zone: Zone: Internet, Permission Set: Internet Restricted_Zone: Zone: Untrusted sites, Permission Set: Nothing Trusted_Zone: Zone: Trusted sites, Permission Set: Internet 11
O politica de securitate este o grupare (logica ) de grupuri de cod si seturi de permisii. Exista 4 nivele de politica de securitate configurabile:
Enterprise Machine User Application Domain 12
Nivelul Enterprise este cel mai inalt nivel. Acesta poate fi configurat folosind Active Directory. Se aplica la tot codul de pe toate calculatoarele din un domeniu. Machine policy e nivelul al doilea. Se aplica la tot codul de pe un calculator. User policy este nivelul al treilea si se aplica per user. Runtime-ul evalueaza Enterprise , Machine si User policy si da assembly-ului drepturile cele mai putine. (rezultate din intersecita politicilor). In general User si Enterprise policy dau acces total, restriciile fiind impuse de catre Machine policy. 13
CAS functioneaza complet independent de sistemul de operare. Aveti chiar si aplicatii diferite de configurare a permisiilor (.NET Framework Configuration Tool la CAS, Windows Explorer la RBS). Atunci cand se determina daca o aplicatie poate rula sunt evaluate atat permisiile CAS cat si cele date de sistemul de operare. Cel mai restrictiv set de permisii rezultat este aplicat. 14
15
Pentru configurarea CAS veti folosii .NET Framework Configuration Tool . Folosind acesta aplicatie puteti: Determina in ce code grup este un assembly. Determina ce permisii are un assembly. Adauga seturi de permisii. Adauga grupuri de cod. Cresteti “increderea” unui assembly. Adaugati zone de securitate. Resetati politicile de securitate. <Show and tell )> 16
In .NET Framework exista si aplicatia caspol, cu care puteti configura CAS din linia de comanda. Exemple: Acordarea full trust unei aplicatii: Caspol –addfulltrust aplicatie.exe Adaugarea unui grup de cod in politica de securitate Macine: Caspol –machine –addgroup Grup_Cod_Parinte Conditie_de_apartenenta Set_de_permisii –name “Nume_grup”
Mai multe detalii in carte paginile 646 – 653. 17
In securitatea declarativa declarati la fiecare assembly/metoda din cod cerintele de securitate de la CAS (de ce permisii are nevoie). Avantajele sunt: Va asigurati ca aplicatia voastra nu poate rula decat daca i se acorda drepturile necesare unei functionari corecte. Sa va creati un sandbox in jurul aplicatiei voastre astfel inca un posibil atacator care ar modifica-o nu ar putea sa o faca sa acceseze resurse pe care nu ar fi trebuit altfel sa le acceseze. Sa verificati daca aplicatia voastra poate sa ruleze cu permisii CAS reduse, deci in medii partially trusted. 18
Pentru fiecare permisie din CAS exista cate o clasa si un atribut in .NET framework. Fiecare clasa sau atribut are un membrii prin care se pot controla permisiile. Ex: OleDbPermissionAtribute.AllowBlankPassword. Din cauza ca sunt foarte multe clase si foarte multe proprietati vom discuta numai pe cele de baza (mostenite de fiecare clasa din CodeAccessSecurityAttribute): Action: Specifica actiunea ce trebuie efectualata. Unrestricred: o valoare Booleana care specifica faptul ca aplicatia va avea nevoie de toate permisiile din clasa. 19
Action ia valori din enumerarea SecurityAction: SecurityAction.RequestMinimum: Aplicatia va avea nevoie de acea permisie pentru a rula. Daca CAS nu ii da acea permisie aplicatia va arunca exceptie System.Security.Policy.PolicyException. SecurityAction.RequestOptimal: Assembly-ul va refuza orice permisie de care nu are nevoie (deci in afara de permisiile pe care le-ati cerut explicit cu RequestMinumum si SecurityAction.RequestOptimal). Daca permisia de care aveti nevoie nu este disponibila nu se va arunca exceptie. Este deci inca nevoie sa folositi RequestMinumum. SecurityAction.RequestRefuse: Assembly-ul vostru va cere explicit sa nu I se acorde o anumita permisie. Nu este aruncata exceptie in caz ca aceasta permisie nu este acordata. 20
Exemple: Urmatorul cod incearca sa acceseze fisierul boot.ini. Acesta va cere explicit permisia de a accesa boot.ini. Daca nu se poate accesa fisierul aplicatia va arunca o exceptie la pornire.
21
Exemplu: Construiti o aplicatie care foloseste Registry-ul. Pentru a lasa aplicatie acces numai la registry, si in registry numai la o zona specifica de registry vezi folosii RegistryPermission si RequestOptimal. OBS: atunci cand folositi request optimal dar dorit sa folosit debuggerul trebuie sa cereti si permisa UIPermission, unrestircted.
22
Exemplu: Puteti combina RequestOptimal si RequestRefuse. Aceata combinatie poate fi inutila, deoarece RequestOptimal deja refuza toate permisiile in afara de cele dorite de voi, deci RequestRefuse poate sa devina redundant. Totusi este folositoare combinarea celor doua atunci cand doriti sa refuzati un subset de permisii pe care le-ati cerut cu RequestOptimal.
23
Ghid de folosire securitate declarativa: Folosit RequestMinumum pentru fiecare permisie de care aveti neaparata si explicita nevoie. Odata ce aveti aceasta permisie nu mai verificati in codul aplicatiei daca aveti acces la functiile respective. Folositi RequestOptimal pentru a cere orice permisie de care ar putea avea nevoie assembly-ul vostru. Incercati sa fiti cat mai expliciti. Folositi RequestRefuse pentru a mai buna rafinare a cerintelor de securitate ale aplicatiei voastre. 24
Pana acum am explicat cum sa protejam intreg assembly-ul prin CAS. In continuare voi explica cum putem proteja metode folosind securitate declarativa sau bucati de cod folosind securitate imperativa. Tipuri de cereri de permisii: Assert: Runtime-ul va ignora faptul ca apelantii unei metode s-ar putea sa nu aiba permisia specificata. Assembly-ul din care fac parte metodele apelante trebuie sa aiba setarea Assert Any Permission That Has Been Granted. Demand: Runtime-ul va arunca o exceptie daca apelantul unei metode (sau apelantii de la nivele superioare din stiva de apel) nu au permisia specificata. Deny: Runtime-ul va elimina permisia specificata. InharitanceDemand: Runtime-ul va arunca o exceptie daca daca assembly-ul ce mosteneste clasa nu are permisia specificata. LinkDemand: Runtime-ul va arunca o exceptie numai daca metoda apelanta (si nu celelalte metode apelanta din stiva de apel) nu are permisia specificata. PermitOnly: Runtime-ul va elimina toate permisiile metodei in afara de cea specificata. 25
Explicatii : Considerati o petrecere. Gazda (metoda voastra) a angajat un bouncer (.net runtime). Sa presupunem ca apare 4 invitati la intrare (apelantii metodei). Daca gazva cere Invitati.LinkDemand bouncer-ul va cere invitatia numai la primul invititat (ceilalti pot intra fara invitatie). Daca gazda cere Invitati.Demand bouncer-ul va cere invitatie de la toti invitatii. Este posibil ca primul invitatat sa garanteze pentru ceilalti. Daca bouncer-ul are destula incredere in el va lasa sa treaca si ceilalti invitati. Acesta este cazul Assert. Dupa ce invitatii au intrat, daca doriti ca invitatii sa nu danseze veti folosii Dansare.Deny. Daca doriti sa nu faca altceva decat sa danseze veti folosii Dasare.PermitOnly. 26
In concluzie: Folositi SecurityAction.PermitOnly atunci cand doriti sa limitati permisiile disponibile pentru o metoda. Includeti toate permisiile de care are nevoie o metoda. Folositi SecurityAction.Deny pentru a filtra mai bine permisiile. Folosit CodeAccessPermission.PermitOnly pentru a reduce imperativ permisiile metodei atunci cand apelati cod in care nu aveti incredere (cod scris de altii de exemplu). Veti folosii CodeAccessPermission.ReverPermitOnly pentru a restaura permisiile metodei. 27
Folositi CodeAccessPermission.Assert cand doriti sa permiteti cod partially trusted pentru a apela pentru care s-ar putea sa nu aveti destule permisii. Folositi CodeAccessPermission.RevertAssert pentru a restaura permisiile. Folosit CodeAccessPermission.Demand numai atunci cand assembly-ul vostru implementeaza mecanisme ce nu sunt incluse in .NET (ex: cod unmanaged).
28
29
30
Pentru a folosii securitatea declarativa pentru protejarea metodelor vezi folosii atribute. Diferentele fata de securitatea declarativa aplicata la assembly-uri sunt: Atributele sunt aplicate metodelor SecurityAction-urile sunt diferite
31
Un alt caz este atunci cand scrieti o clasa si doriti ca toti developeri care mostenesc clasa voastra sa aiba o anumita permisie, folosititi InheritanceDemand.
32
Pentru fiecare SecurityAction exista un CodeAccessPermission.
33
Atunci cand nu dorum sa folosim SecurityAction.Demand putem folosii metoda IsGranted din clasa SecurityManager FileIOPermission filePermission = new FileIOPermission(FileIOPermission.Read, @“C:\”); if (SecurityManager.IsGranted(filePermission)==true) //ceva else //altceva 34
Intodeauna folositi securitatea declarativa pentru a limita permisiile acordate assembly-ului la minimul necesar. Folositi SecurityAction.Deny si SecurityAction.PermitOnly pentru a restrictiona permisiile pe care le au metodele. Folositi CodeAccessPermission.Deny si CodeAccessPermission.PermitOnly pentru a restrictiona codul untrusted. 35
Atacatorii induc de multi ori erori in aplicatii. Apoi exploateaza aceste erori pentru a executa cod care nu s-ar putea executa in conditii normale. Din acest motiv este recomandat sa folositi PermitOnly atunci cand tratati erori. try { } catch { EventLogPermission elPerm = new EventLogPermission(PermissionState.Unrestricted); elPerm.PermitOnly(); //tratare exceptie CodeAccessPermision.RevertPermitOnly(); } 36
Folosirea CAS scade performantele aplicatiei. Folosirea metodei Demand este cea mai costisitoare. O modalitate de imbunatatire a performantelor este sa folositi LinkDemand. Alte posibilitate este sa folositi metoda Assert, care face runtime-ul sa omita orice verificari de securitate. Diferenta intre LinkDemand si Assert este ca LinkDemand este acordat de metoda ce este apelata in timp ce Assert este prezentat de metoda apelanta. 37
38
Pentru a putea folosii Assert assembly-ul trebuie sa aiba flag-ul SecurityPermissionsFlag.Assertion setat. Acesta este reprezentat de optionea Assert Any Permission That Has Been Granted in dialogul Security. Zonele FullTrust, LocalIntranet si Everything au acest flag setat. Folosint Assert puteti (de exemplu) sa permiteti unei aplicatii din zona Internet sa scrie pe disc. Tot ce trebuie sa faceti este sa scrieti o metoda ce scrie pe disk, cu atributul AllowPartialyTrustedCallersAttribute. Aplicatia din zona internet va rula metoda si deci va putea scrie pe disk. [assembly: AllowPartialyTrustedCallers] Dupa apelul metodei Assert trebuie readuse permisiile la forma initiala. Aceasta se face prin apelul metodei CodeAccessPermission.RevertAssert. 39
40
Assert are unele limitari: Nu poate fi folosit decat o singura data pe metoda. Daca doriti assert la mai multe permisii trebuie sa creati un set propriu de permisii. Ex: PermissionSet myPerms = new PermissionSet(PermissionState.None); myPerms.Add(new FileIOPermission(FileIOPermissionAccess.Read,”C:\boot.ini”)); myPerms.Add(new FileIOPermission(FileIOPermissionAccess.Read,”C:\Windows”)); myPerms.Assert(); Aplicatia tot este supusa limitarilor RBS. Ex: daca un user nu are acces la un fisier, nici aplicatiile pe care le ruleaza acest user nu vor avea acces. 41