Bezpečnost software .NET Framework .

Transkript

Bezpečnost software .NET Framework .
Bezpečnost software .NET Framework .
Cílem tohoto tutoriálu bude seznámit čtenáře ze základy zabezpečení u projektů na bázi .NET Framework. Na základě
připomínek jsem tento tutoriál rozšířil. Je nutno si uvědomit, že k pochopení zabezpečení v celém rozsahu musíte
zvládnout přidělování a uvolňování paměti, práce se zásobníkem a případně API-PInvoke. V tomto článku jsem
neřešil zabezpečení pro IIS aplikace a mobilní aplikace.
Pokud vytvoříme nějaký projekt budeme požadovat, aby náš software pracoval na různých počítačích nebo
na webovém serveru. Nemá být náchylný ke změnám od různých uživatelů a neměl by ovlivňovat stávající operační
systém na kterém bude nainstalován. Bezpečnost se dříve nejčastěji řešila na základě zjišťování identity uživatele.
Veškeré operace byly kontrolovány podle práv, která přidělil administrátor. Takto řešený systém již nevyhovuje.
Pokud se podíváme do nedaleké minulosti začátek nové éry zavedl Microsoft Transaction Server, který založil systém
bezpečnosti na rolích. Role sdružují uživatele nezávisle na tom, v jakých systémových skupinách se nacházejí. Tento
princip převzal .NET Framework a ještě ho rozšířil.
Bezpečnost na platformě .NET se dotýká těchto oblastí.
 Typová bezpečnost – programy pracují pouze s pamětí, která byla alokována pro jejich objekty. Na příklad
třída, která je typově bezpečná neumožní přistupovat k soukromým členům třídy žádným způsobem. Přístup
je garantován pouze přes její definované rozhraní.
 Přístupové bezpečnosti kódu - tento typ bezpečnosti umožňuje nastavit důvěryhodnost kódu v závislosti na
tom, odkud kód pochází a dalších aspektech identity kódu. Můžeme nastavit, které operace s danou
identitou může vykonávat a které nikoliv.
 Identity kódu – tuto zabezpečují služby, které zavádějí aplikaci do paměti. Informace o vydavateli, místě ze
kterého kód pochází a podobně.
 Deklarativního a imperativního řízení bezpečnosti – v další části se budeme zabývat podrobněji.
 Povolení – CLR umožňuje vykonávat pouze operace, na které má kód povolení. Zde se rozlišují dva typy
povolení:
o Povolení pro přístup ke kódu – základní nástroj (přístup k chráněným systémovým zdrojům a práva
pro spuštěných chráněných operací, volání funkcí neřízeného kódu a podobně)
o Povolení identity
 Bezpečnosti založené na rolích – využívá objekt Principal, v další části se budeme zabývat podrobněji.
 Kryptografických služeb – sada kryptografických objektů, šifrovací algoritmy, hashovací funkce.
Zde mi dovolte malé odbočení, pro oživení vaší paměti. Problémem při nasazování aplikací v prostředí .NET vyřešilo
zavedení Assembly.
Důvodů zavedení bylo několik:
 Aplikace musí být samostatné – snadná instalace nebo reinstalace.
 Aplikace musí obsahovat čísla verzí a musí být na ně vázána.
 Čísla verzí komponent – vedle vlastní verze si musí aplikace pamatovat čísla verzí komponent, které interně
používá.
 Musí podporovat Side-by-side komponenty – existence dvou a více verzí stejné komponenty na jednom
počítači je realitou a jedním z velkých problémů současných instalací.
 Musí umožňovat izolaci aplikace – aplikace nesmí být náchylná k poruchám způsobených změnami
provedenými na počítači.
 Musí zajistit bezpečný přístup ke kódu.
 Komponenty musí obsahovat informace o veřejných typech.
Co je assembly?
Assembly je logickou kolekcí, stávající se z jednoho nebo více .exe, .dll nebo .module souboru a zdrojů doplněných o
manifest. Assembly je také často definována jako programová jednotka určená k nasazení a opakovanému použití,
řízení verzí a bezpečnosti. Assembly je velice podobná dnešní dynamicky linkované knihovně, jsou však na ní kladeny
vyšší požadavky. Tyto vyšší požadavky jsou splněny přidáním tzv. manifestu do Assembly.
Stránka 1
Manifest je blok metadat obsahující tyto informace:
 identita – jméno, verze a kultura;
 seznam souborů + kryptografické zabezpečení;
 odkaz na další použité assembly + jejich verze;
 exportované (veřejně viditelné) typy a zdroje;
 bezpečnostní požadavky.
V průběhu času se měnilo zabezpečení u .NET Framework, zlom nastal při nasazení verze 4.0 a vyšší. Microsoft
rozděluje .NET Framework na dva různé typy zabezpečení (Rozdíl Level1 a Level2 MSDN), na zabezpečení
SecurityRuleSet.Level1 a SecurityRuleSet.Level2. My se budeme v tomto článku zabývat SecurityRuleSet.Level2, to
znamená zabezpečením platícím od .NET Framework verze 4.0 a vyšším. Zaměřím se na praktické ukázky kódu.
Ve všech ukázkách bude doplněno AssemblyInfo.cs o tento kód:
using Systém;
using System.Security;
[assembly: SecurityRules(SecurityRuleSet.Level2)] //1
[assembly: CLSCompliant(true)]
//2
1. Budeme používat .NET Framework minimálně verze 4.0
2. Veškerý kód, který bude generován kompilátorem, bude možno používat i u jiných jazyků na příklad Linuxu a
podobně. Bližší popis v MSDN.
Pro pochopení uvedu definice názvů, které jsou v této ukázce použity:




Attributy – jsou zvláštní údaje o entitách v kódu (třídách, metodách, vlastnostech a podobně), které se do
zdrojového kódu vkládají pomocí speciální syntaxe. Attributy mohou měnit chování těchto entit, nebo
mohou být uloženy jako dodatečné kusy metadat v kompletech. (konec citátu z knihy Visual C++ .NET).
Attributy jsou začleněny do programu v době kompilace. Atributy jsou přístupné pomocí reflexe. Pokud
uplatníme oprávnění pomocí atributů, nelze zachycovat žádné výjimky v případě selhání. ( nemůžeme nikam
umístit try-catch-finally ).
Transparentní kód – může volat jiný transparentní kód nebo částečně důvěryhodný kód. Může provádět
pouze akce povolené částečně důvěryhodnou sadou oprávnění náležící doméně. Existuje několik omezení
uvalená na transparentní kód. Zejména tento kód nemůže provádět:
1. Volat SecurityCricital kód, ale může volat také SecuritySafeCritical kód.
2. Provádět metodu Assert nebo zvyšovat úroveň oprávnění.
3. Obsahovat nebezpečný (unsafe) nebo neověřitelný (unverifiable) kód.
4. Nelze volat P/Invoke metody.
5. Přepsat nebo dědit kritické typy a metody.
6. Volat člen, který je chráněn pomocí LinkDemand.
Částečně důvěryhodný kód je v .NET Framework 4 a výše, předefinován jako transparentní kód.
Transparentní model kreslí bariéru mezi kódem, který může dělat privilegované věci (kritický kód), jako je
například volání nativního kódu a kódem, který tyto věci dělat nemůže (transparentní kód). Transparentnost
vylučuje použití LinkDemand k identifikaci plně důvěryhodného kódu a ovlivňuje pravidla pro spuštění
částečně důvěryhodného kódu. (MSDN)
Kritický kód je malá část zdrojového kódu, kde dochází k přístupu ke sdílenému prostředku (např. sdílená
data, která označujeme jako kritická oblast), ke kterému nemohou současně přistupovat dva nebo více
procesů či vláken. Programy, které usilují o vstup do kritické sekce, musí použít nějaké synchronizační
primitivum, které má za úkol zajistit do kritické sekce exkluzivní přístup a zároveň konečnou dobu čekání na
povolení ke vstupu.
Stránka 2
Používání atributů [SecurityTransparent], [SecuritySafeCritical] a [SecuritySafeCritical]

Použití na úrovni sestavy (AssemblyInfo.cs)
1. Žádný atribut - všechny typy a členové tříd jsou transparentní, ale mohou být také kritické nebo
SecuritySafeCritical mimo případů, kdy je porušeno pravidlo dědičnosti.
2. [assembly: SecurityTransparent] - všechny typy a členové jsou transparentní. Lze použít pouze
v AssemblyInfo.cs.
3. [assembly : SecurityCritical] – všechen kód v této sestavě je kritický. Pokud přepíšeme virtuální nebo
abstraktní metodu nebo implementujeme metodu rozhraní, pak musíme explicitně okomentovat
metodu jako [SecurityCritical] nebo [SecuritySafeCritical].
4. [assembly: SecuritySafeCritical] – nelze použít.

Přepis vzorů pro interface a virtual.

Base virtual/interface member
Override/interface
Transparent
Transparent
Transparent
SafeCritical
SafeCritical
Transparent
SafeCritical
SafeCritical
Critical
Critical
Pravidla dědičnosti.
Pravidla dědičnosti musí být implementována v tomto pořadí:
Transparent < SafeCritical < Critical
V tabulce jsou uvedeny povolené typy dědičnosti.
Základní třída
Odvozená třída může být
Transparent
Transparent
Transparent
SafeCritical
Transparent
Critical
SafeCritical
SafeCritical
SafeCritical
Critical
Critical
Critical
Stránka 3
Základní metoda
Odvozená metoda může být
Transparent
Transparent
Transparent
SafeCritical
SafeCritical
Transparent
SafeCritical
SafeCritical
Critical
Critical
Na příkladu si ukážeme použití kritického kódu:
Tento příklad ukáže jak je řešena funkce FileStream(…) ze jmeného prostoru Systém.IO.
Základem je API funkc SetFilePointer(…), která přemísťuje ukazatel pozice v souboru. Tento ukazatel indikuje, kde se
v souboru provede čtení nebo zápis. Pokud pracujeme v aplikacích s násobným přístupem
(multithread aplikace) musíme být při nastavování opatrní. Cesta zpracování zpráv sdílí stejné handle, a aktualizuje
ukazatel souboru, musí být tato sekvence chráněna použití objektu kritické sekce nebo objektu mutexu.
Tento příklad ukazuje jak přejít z kritického kódu na transparentní kód.
[SecurityCritical]
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern unsafe uint SetFilePointer(
[In] SafeFileHandle hFile,
[In] int lDistanceToMove,
[Out] int* lpDistanceToMoveHigh,
[In] EMoveMethod dwMoveMethod
);
Voláme API funkci (nebezpečný kód použití pointru)
[SecurityCritical]
internal static unsafe long SetFilePointer(SafeFileHandle handle, long offset, SeekOrigin origin, out int hr)
{
hr = 0;
int lo = (int) offset;
int num1 = (int) (offset >> 32);
int num2 = UnsafeNativeMethods.SetFilePointerWin32(handle, lo, &num1, (int) origin);
if (num2 == -1 && (hr = Marshal.GetLastWin32Error()) != 0)
return -1L;
else
return (long) (uint) num1 << 32 | (long) (uint) num2;
}
Zde vidíme přechod mezi kritickým a transparentním kódem.
//zde vidíme přechod mezi kritickým a transparentním kódem
//using Systém.IO.FileStream
[SecuritySafeCritical]
private long SeekCore(long offset, SeekOrigin origin)
{
Stránka 4
int hr = 0;
long num = Win32Native.SetFilePointer(this._handle, offset, origin, out hr);
//nějaký kód
}
Transparentní kód.
//using Systém.IO
[SecuritySafeCritical]
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync)
{
//nějaký kód
this.SeekCore(0L, SeekOrigin.Current);
//nějaký kód
}
Bezpečnostní koncepty můžeme rozdělit na dvě rozdílné skupiny:
1. Role Based Security
Role jsou často používány ve finančních a obchodních aplikacích. Například, aplikace může stanovit omezení velikosti
transakce zpracovávání v závislosti na tom, zda uživatel, je členem zadané úlohy. Úředníci mohou mít povolení ke
zpracování transakce, které jsou menší než stanovený práh, orgány dohledu mohou mít vyšší limit, a místopředsedů
by mohla mít ještě vyšší limit (nebo bez omezení vůbec). Zabezpečení založené na rolích lze použít také pro aplikace,
které vyžadují několik povolení k provedení akce. Takovým případem by mohl být nákupní systém, ve kterém každý
zaměstnanec může generovat požadavek na nákup, ale jen nákupčí jej může provést.
Pro zajištění snadného používání a souladu se zabezpečením přístupu ke kódu .NET Framework umožňuje
zabezpečení založené na rolích, realizované objekty v System.Security.Principal, které umožňují společnému
jazykovému modulu runtime provést autorizaci způsobem, který je podobný bezpečnostním kontrolám přístupového
kódu.
PrincipalPermission je třída představující identitu nebo roli a je kompatibilní jak s deklarativními a bezpečnostními
kontrolami.
Existují dva způsoby, jak vytvořit WindowsPrincipal objekt, v závislosti na tom, zda kód musí opakovaně provádět
ověřování na základě rolí, nebo kód ověřuje pouze jednou. WindowsPrincipal umožňuje zkontrolovat členství ve
skupině Windows pro uživatele a provést kontrolu kódu.
Tento příklad ukazuje, část třídy, kterou může spustit pouze uživatel, který má práva administrátora.
using System;
using System.Security.Permissions;
using System.Security.Principal;
using System.Security;
class TestSecurityPrincipal
{
public static void Main()
{
/* Před k volání CurrentDemand metodu, je nezbytné stanovit hlavní zásady pro aktuální doménu aplikace
hodnotu výčtu WindowsPrincipal. Ve výchozím nastavení hlavních zásad UnauthenticatedPrincipal. Pokud
hlavní zásady není nastaven na WindowsPrincipal, na hlavní oprávnění vyžádaného volání se nezdaří. */
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
Stránka 5
//hodnota null – bude platit u windows pro skupinu administrátorů na libovolném PC
PrincipalPermission principalPerm = new PrincipalPermission(null, "administrators");
try
{
principalPerm.Demand();
Console.WriteLine("Žádost o spuštění uspěla.");
}
catch(SecurityException ex)
{
Console.WriteLine("Žádost o spuštění neuspěla - " + ex.Message);
}
finally
{
Console.ReadLine();
}
}
2. Zabezpečení přístupu ke kódu.
Common Language Runtime (CLR) umožňuje kód provádět pouze ty operace, na které má kód oprávnění k
provedení. Bezpečnostní systém CLR vynucuje bezpečnostní politiky tím, že zabraňuje neoprávněnému přístupu k
chráněným zdrojům a operacím. Použitím zabezpečení přístupu ke kódu, můžeme provádět následující:
 Omezit, co váš kód může dělat
 Omezení, které kód může volat cizí kód
 Identifikovat kód
Zabezpečení přístupu ke kódu se skládá z těchto prvků:
 oprávnění
 sady oprávnění
 skupiny kód
 důkaz
 politika
Oprávnění:
Oprávnění představuje přístup ke chráněným zdrojům nebo schopnost provádět chráněné operace. NET Framework
poskytuje několik tříd oprávnění, na příklad FileIOPermission (při práci se soubory), UIPermission (povolení k použití
uživatelského rozhraní), SecurityPermission (Definuje obor názvů tříd, které řídí přístup na operace a prostředky na
základě zásad.)
Sady oprávnění:
Sada oprávnění je sbírka oprávnění. Můžeme si dát FileIOPermission a UIPermission do svého vlastní oprávnění
souboru a říkat " MyPermissionSet ". Sada oprávnění může obsahovat libovolný počet oprávnění, na příklad FullTrust,
LocalIntranet, Internet, Execution a Nothing a jsou v sadě oprávnění v rozhraní .NET Framework. FullTrust má
všechna oprávnění na světě, zatímco Nothing nemá vůbec žádné oprávnění.
Stránka 6
Kódové skupiny:
Skupina Code je logické seskupení kódu, který má nastavenou podmínkou pro členství. Kód z webové stránky může
patřit do jedné kódové skupiny, kód obsahující specifický silný název může patřit do jiné kódové skupiny a kód z
konkrétní sestavy může patřit do jiné kódové skupiny. Tyto jsou vestavěné ve skupinách kódu jako
My_Computer_Zone , LocalIntranet_Zone , Internet_Zone atd. Stejně jako sady oprávnění, můžeme vytvářet skupiny
kde kód bude plnit naše požadavky na základě důkazů předložených .NET Framework. Site , Strong Name , Zone a
URL toto jsou některé typy důkazů zde ukázaných.
Politika:
Bezpečnostní politika je konfigurovatelný soubor pravidel, která CLR sleduje při stanovení oprávnění udělit kódu. K
dispozici jsou čtyři úrovně politiky - Enterprise , Machine , User a ApplicationDomain, každá pracuje nezávisle na
sobě. Každá úroveň má své vlastní skupiny kódů a sady oprávnění. (Viz obr. použit z MSDN)
Pro kódování můžeme použít dva druhy kódování (deklarativní a imperativní).
Deklarativního zabezpečení:
Deklarativní syntax využívá atributy pro označení metody, třídy nebo sestavy na získání potřebných informací
o zabezpečení. Takže když se sestavují, jsou uspořádány v části metadat sestavy.
Deklarativní požadavky pro PrincipalPermission fungují stejným způsobem, jako deklarativní požadavky pro
přístupové oprávnění ke kódu. Požadavky mohou být umístěny na úrovni třídy, stejně jako u jednotlivých metod,
vlastností nebo událostí. Pokud je deklarativní požadavek umístěn na úrovni třídy i člena, tak deklarativní požadavek u
člena přepíše (nebo nahradí) požadavek na úrovni třídy.
Příklad 1 :
Volající musí mít práva administrátora.
class SecurityTest
{
public static void Main()
{
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
MyClass cx = new MyClass();
Console.ReadLine();
}
}
[PrincipalPermissionAttribute(SecurityAction.Demand, Name = null, Role = "administrators")]
public class MyClass
{
public MyClass() { }
// všechny tyto metody
public void MyMethod_A() { }
public void MyMethod_B() { }
}
Stránka 7
Chyba pokud není uživatel ve skupině administrátors.
Příklad 2:
Tento příklad řeší přístup do složky "c:\MyDir". Pokud kdekoliv ve třídě MyClass je volán jiný název složky, je
generována chyba.
class SecurityTest
{
public static void Main()
{
MyClass cx = new MyClass();
Console.ReadLine();
}
}
[FileIOPermissionAttribute(SecurityAction.PermitOnly, ViewAndModify = @"c:\MyDir")]
public class MyClass
{
public MyClass()
{
DirectoryInfo di = new DirectoryInfo(@"c:\MyDir");
if(!di.Exists)
{
di.Create();
Console.WriteLine("Direktory neexistuji");
Console.ReadLine();
}
//nějaký kód
di.Delete();
}
}
Chyba pokud je volána jiná složka.
Příklad 3 použití třídy UIPermission.
Pokud se podíváme do dokumentace MSDN, můžete vidět tyto veřejné vlastnosti:


Action - jedna z hodnot v SecurityAction enum (společná)
Unrestricted - neomezený přístup ke zdroji (společné)
Stránka 8


Clipboard - typ přístupu do schránky, jedna z hodnot v UIPermissionClipboard enum ( UIPermission
specifické)
Window - typ přístupu k oknu, jednu z hodnot v UIPermissionWindow enum ( UIPermission konkrétní).
Action a Unrestricted vlastnosti jsou společné pro všechny třídy oprávnění. Clipboard a Window vlastnosti jsou
specifické pro UIPermission třídy. Musíte zajistit akci, kterou užíváte a další vlastnosti, které jsou specifické pro třídu
oprávnění, který používáte.
Takže v tomto případě můžete psát jako následující:
Možnost použití přístupu do schránky bez omezení, volaná funkce musí mít určené oprávnění.
[UIPermission (SecurityAction.Demand, Clipboard = UIPermissionClipboard.AllClipboard)]
public void FA(){//nějaký kód }
nebo s oběma Clipboard a Window vlastnosti:
Uživatelé mohou používat všechna okna windows, pro operace se schránkou, omezení jako předešlý příklad.
[UIPermission (SecurityAction.Demand, Clipboard = UIPermissionClipboard.AllClipboard,
Window = UIPermissionWindow.AllWindows)]
public void FA(){//nějaký kód }
Chcete-li deklarovat povolení s neomezeným přístupem, můžete to udělat jako následující:
[UIPermission (SecurityAction.Demand, Unrestricted = true)]
public void FA(){//nějaký kód }
Stránka 9
Nyní se podíváme co nám nabízí výčet SecurityAction :
Tento výčet určuje zabezpečení akcí, které lze provést pomocí deklarativního zabezpečení. Nabízí tyto členy:
 Assert -> je metoda, kterou lze volat na třídy oprávnění přístupu ke kódu a na třídu PermissionSet. Metodu
Assert můžete použít k tomu, abyste vašemu kódu povolili (a volajícím ve směru server-klient) provedení
akcí, ke kterým váš kód má oprávnění k provedení, ale jeho volající je mít nemusí. Kontrolní výrazy
zabezpečení mění normální proces, který provádí modul runtime během kontroly zabezpečení. Zde bych
použil příklad z MSDN.
Budeme předpokládat, že následující příkazy jsou pravdivé u sestavení A, B, C, E a F a dvou oprávněních P1
a P1A:
 P1A představuje právo pro čtení .txt souborů na disku C.
 P1 představuje právo pro čtení všech souborů na disku C.
 P1A a P1 jsou obě typu FileIOPermission a P1A je podmnožinou P1.
 Sestavením E a F bylo uděleno oprávnění P1A.
 Sestavení C bylo uděleno oprávnění P1.
 Sestavením A a B, nebylo uděleno ani oprávnění P1 ani P1A.
 Metoda A je obsažena v sestavení A, metoda B je obsažena v sestavení B atd.
V tomto scénáři metoda A volá B, B volá C, C volá E a E volá F.
Metoda C uplatňuje oprávnění pro čtení souborů na disku C (oprávnění P1) a metoda E požaduje oprávnění
ke čtení txt souborů na disku C (oprávnění P1A). Když je za běhu v metodě F objeven požadavek, je
provedeno procházení zásobníku, aby se zkontrolovaly oprávnění všech volajících metody F, počínaje E.
Metodě E bylo uděleno oprávnění P1A, takže procházení zásobníku pokračuje zkoumáním oprávnění metody
C, kde je objeven kontrolní výraz. Protože požadované oprávnění (P1A) je podmnožinou uplatňovaného
oprávnění (P1), procházení zásobníku se zastaví a kontrola zabezpečení automaticky uspěje. Nezáleží na tom,
že sestavením A a B nebylo uděleno oprávnění P1A. Metoda C pomocí uplatňování P1 zajišťuje, že její volající
mohou přistupovat k prostředku, který je chráněn oprávněním P1, dokonce i když volajícím nebylo uděleno
oprávnění pro přístup k tomuto prostředku.
Rečeno jinak, umožní kódu přístup k prostředkům, které nejsou volající funkci normálně k dispozici.
Příklad 4.
Následující příklad ukazuje deklarativní syntaxi pro přepsání kontroly zabezpečení pomocí metody Assert.
Všimněte si, že syntaxe FileIOPermissionAttribute používá dvě hodnoty:
Stránka 10
výčet SecurityAction a umístění souboru nebo adresáře, kterému je uděleno oprávnění. Volání Assert způsobí, že
požadavky pro přístup k souboru C:\Temp\Log.txt proběhnou úspěšně, přestože volající nejsou zkontrolováni, zda
mají oprávnění pro přístupu k souboru.
//C#
[FileIOPermission(SecurityAction.Assert, Append = @"C:\Temp\Log.txt")]
public void MakeLog()
{
StreamWriter TextStream = new StreamWriter(@"C:\Temp\Log.txt");
TextStream.WriteLine("Tento protokol byl vytvořen dne: {0}", DateTime.Now);
TextStream.Close();
Console.WriteLine("OK");
}
Assert pro VB.NET

Demand -> je metoda, která vynutí výjimku zabezpečení v době spuštění. Požaduje, aby všechny volající
funkce v zásobníku volání měly určená oprávnění.

LinkDemand -> nepoužívat u .NET Framework 4. Místo ní používat SecurityCriticalAttribute. Omezit
používání plně důvěryhodné aplikace nebo pomocí Demand omezit částečně důvěryhodného volajícího.

InheritanceDemand -> požaduje, aby bylo odvozeným třídám uděleno určené oprávnění. Platí pro dědění a
přepsání (overriding).

PermitOnly -> odmítne následné požadavky na prostředky, které nejsou explicitně uvedeny pomocí
hodnoty PermitOnly.
Prohlášení o zabezpečení akce
Čas akce
Podporované cíle
LinkDemand (nepoužívejte v .NET Framework 4)
Just-in-time kompilace
Třídy, metody
InheritanceDemand
Čas načítání
Třídy, metody
Demand
Čas spuštění
Třídy, metody
Assert
Čas spuštění
Třídy, metody
Deny (zastaralé v .NET Framework 4)
Čas spuštění
Třídy, metody
PermitOnly
Čas spuštění
Třídy, metody
RequestMinimum (zastaralé v .NET Framework 4)
Poskytnutí času
Sestavení
RequestOptional (zastaralé v .NET Framework 4)
Poskytnutí času
Sestavení
RequestRefuse (zastaralé v .NET Framework 4)
Poskytnutí času
Sestavení
Skrýt Kopírovat kód
Příklad 5.
InheritanceDemand -> Dědické nároky mohou být aplikovány na třídy nebo metody. V případě, že je aplikován na
třídu, pak všechny třídy, které pocházejí z této třídy, musí mít oprávnění zadaná.
Stránka 11
[SecurityPermission (SecurityAction.InheritanceDemand)]
Private class MyClass ()
{
// cokoliv
}
Příklad 6.
V případě, že se použije metodu, pak všechny třídy, které pocházejí z této třídy, musí mít oprávnění zadaná potlačit
tuto metodu.
Private class MyClass ()
{
public class MyClass () {}
[SecurityPermission (SecurityAction.InheritanceDemand)]
public virtual void MyMethod ()
{
// nějaký kód
}
}
Příklad 7.
Následující příklad kódu používá požadavek dědičnosti pro vyžadování, aby jakákoliv třída, která dědí z třídy MyClass
musela mít vlastní oprávnění CustomPermissionAttribute. Toto oprávnění je hypotetické vlastní oprávnění a
neexistuje v rozhraní .NET Framework. Požadavek je vytvořen předáním CustomPermissionAttribute a hodnoty výčtu
SecurityAction.InheritanceDemand.
//C#
[CustomPermissionAttribute(SecurityAction.InheritanceDemand)]
public Class MyClass
{
public MyClass()
{
}
public virtual string ReadData()
{
// Přístup k vlastnímu zdroji
}
}
//VB.NET
<CustomPermissionAttribute(SecurityAction.InheritanceDemand)> _
Public Class MyClass
Public Sub New()
End Sub
Public Overridable Function ReadData() As String
' Přístup k vlastnímu zdroji
End Function
End Class
Stránka 12
Příklad 8.
PermitOnly -> Volání PermitOnly má v podstatě stejný účinek jako volání Deny, ale má jiný způsob specifikování
podmínek, za kterých by měla selhat kontrola zabezpečení. Místo prohlašování, že specifikovaný prostředek není
přístupný, jak to dělá Deny, metoda PermitOnly říká, že pouze prostředek, který specifikujete je přístupný. Proto
volání PermitOnly na oprávnění X je stejné jako volání Deny na všechna oprávnění kromě oprávnění X. Pokud voláte
PermitOnly, váš kód může být použit pouze pro přístup k prostředkům, které jsou chráněné oprávněními, které jste
určili, když jste volali PermitOnly. Použijte PermitOnly místo Deny, když je pohodlnější popsat prostředky, které
mohou být přístupné místo prostředků, které přístupné být nemohou.
WebPermission myWebPermission = new WebPermission (NetworkAccess.Connect,
"Http://www.somewebsite.com");
myWebPermission.PermitOnly ();
// něco provádět
CodeAccessPermission.PermitOnly (); // zrušit PermitOnly
PermitOnly deklarativní VB.NET.vb
Příklad 9.
Následující fragmenty kódu ukazují deklarativní syntaxi pro přepsání kontrol zabezpečení pomocí PermitOnly.
Volající nemohou použít tento kód pro přístup k žádným chráněným prostředkům kromě prostředků uživatelského
rozhraní.
using System.Security.Permissions;
using System;
public class MyClass
{
public MyClass()
{
}
[UIPermissionAttribute(SecurityAction.PermitOnly, Unrestricted = true)]
public void ReadRegistry()
{
//Access a UI resource.
}
}
Ukázka imperativního zabezpečení:
Příklad 10.
Následující fragmenty kódu ukazují imperativní syntaxi pro přepsání kontroly zabezpečení pomocí metody Assert.
 V tomto příkladě je deklarována instance objektu FileIOPermission.
 Jeho konstruktoru je předán FileIOPermissionAccess.AllAccess, aby definoval typ povoleného přístupu.
 Následován je řetězcem, který popisuje umístění souboru.
 Jakmile je jednou definován objekt FileIOPermission,
 Musíte pouze volat jeho metodu Assert pro přepsání kontroly zabezpečení.
public void MakeLog()
{
FileIOPermission FilePermission = new FileIOPermission(FileIOPermissionAccess.AllAccess,
@"C:\Temp\Log.txt");
FilePermission.Assert();
StreamWriter TextStream = new StreamWriter(@"C:\Temp\Log.txt");
Stránka 13
TextStream.WriteLine("Tento protokol byl vytvořen dne: {0}", DateTime.Now);
TextStream.Close();
Console.WriteLine("OK");
}
Imperativní syntax používá metodu runtime volání k vytvoření nové instance bezpečnostních tříd.
Pro imperativní požadavky můžete volat metodu Demand náležící objektu PrincipalPermission, pokud chcete zjistit, zda
aktuální objekt zabezpečení představuje zadanou identitu, roli nebo obojí. Za předpokladu, že
objekt PrincipalPermission je správně sestavený a nazvaný MyPrincipalPermission, imperativní požadavky mohou
být volány pomocí následujícího kódu.
Příklad 11.
public void Fx()
{
FileDialogPermission fileDlgPermission = new FileDialogPermission(PermissionState.Unrestricted);
fileDlgPermission.Demand ();
if (myDlgForm.ShowDialog () == DialogResult.OK)
MessageBox.Show (myDlgForm.FileName);
}
nebo:
public Classs MyClass
{
public Moje_třída () {}
public void Method_A ()
{
// Něco udělat
FileIOPermission myPerm = new FileIOPermission (PermissionState.Unrestricted);
myPerm.Demand ();
// Zbytek kódu nebude vykonán, pokud se to nepovedlo,
// Něco udělat
}
// Žádné požadavky
public void Method_B ()
{
// Něco udělat
}
}
Hlavní rozdíl mezi těmito je:
 deklarativní volání jsou hodnoceny v době kompilace
 imperativní volání jsou hodnoceny za běhu.
Namespace System.Security.
Obsahují třídy, které zastupují systém zabezpečení rozhraní .NET Framework, včetně oprávnění. Podřízené skupiny
názvů poskytují typy, které umožňují řídit přístup k zabezpečeným objektům a auditovat je. Zajišťují ověřování
uživatelů, poskytují kryptografické služby, řídí na základě zásad přístup k operacím a prostředkům a podporují správu
přístupových práv k obsahu vytvořenému v dané aplikaci.
Zabezpečují oprávnění základní třídy.(některé třídy - příklady)
Stránka 14




CodeAccessPermission -> Definuje základní strukturu všech přístupových oprávnění ke kódu.
PermissionSet -> Představuje kolekci, která může obsahovat mnoho různých druhů oprávnění.
SecurityException -> Výjimka, která je vyvolána, když je zjištěna chyba zabezpečení.
SecureString -> Představuje text, který by měly být důvěrný. Text je šifrovaný pro ochranu osobních údajů, je
odstraněný z paměti počítače, pokud již není potřeba.
Namespace System.Security.AccessControl (ACL).
Množina názvů, která poskytuje programovací prvky, akce, související se zabezpečením na zabezpečené objekty
auditu a řízení přístupu k těmto objektům.(některé třídy - příklady)
 FileSecurity -> Zabezpečuje řízení přístupu a zabezpečení pro soubor auditu. Od této třídy nelze dědit. Třída
představuje sadu pravidel práv přístupu a auditování. Každé pravidlo přístupu je zastoupené
objektem FileSystemAccessRule a každé pravidlo auditu je zastoupeno objektem FileSystemAuditRule.
Příklad 12.
Soubor, který chceme přidat musí existovat.
using System;
using System.IO;
using System.Security.AccessControl;
class FileTest
{
public static void Main()
{
try
{
string fileName = @"c:\Temp\Log.txt";
Console.WriteLine("Přidání položky pro řízení přístupu "
+ fileName);
// Přidání položky pro řízení přístupu k souboru - přístup povolen
AddFileSecurity(fileName, @"administrators",
FileSystemRights.ReadData, AccessControlType.Allow);
Console.WriteLine("Odstranění položky řízení přístupu k souboru. "
+ fileName);
// Odstranění položky řízení přístupu k souboru.
RemoveFileSecurity(fileName, @"administrators",
FileSystemRights.ReadData, AccessControlType.Allow);
Console.WriteLine("Hotovo.");
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
Console.ReadLine();
}
}
Stránka 15



DirectorySecurity -> Řízení přístupu a auditování zabezpečení adresáře. Od této třídy nelze dědit.
MutexAccessRule -> Sadu práv přístup povolen nebo odepřen uživateli nebo skupině. Od této třídy nelze dědit.
RegistrySecurity -> Zabezpečení řízení přístupu systému Windows pro klíč registru. Od této třídy nelze dědit.
Namespace System.Security.Authentication.(některé výčty)
Poskytuje sadu výčtů, které popisují zabezpečení spojení. Tyto výčty patří CipherAlgorithmType,ExchangeAlgorithmType, HashAlgorithmType, a SslProtocolType.
 ExchangeAlgorithmType -> výčet. Určuje algoritmus použitý k vytvoření sdíleného klíče klienta a serveru.
 CipherAlgorithmType -> výčet. Definuje možné šifrovací algoritmy pro SslStream třídu.
Namespace System.Security.Cryptography.
Obor názvů poskytuje kryptografických služeb, včetně zabezpečeného kódování a dekódování dat stejně jako mnoho dalších
operací. Například algoritmus hash, generování náhodných čísel a ověřování zpráv.
 AesCryptoServiceProvider -> Provádí symetrické šifrování a dešifrování pomocí kryptografických aplikačních
programovacích rozhraní (CAPI), provádění algoritmus standard AES (Advanced Encryption Standard).
Příklad 13.
Příklad ukazuje, jak šifrovat a dešifrovat pomocí ukázkových dat třídy AesCryptoServiceProvider.
using System;
using System.IO;
using System.Security.Cryptography;
class AesCryptographyExample
{
public static void Main()
{
try
{
string original = "Data, které chceme zašifrovat";
// Vytvoření nové instance AesCryptoServiceProvider class.
// Vytvoření nového klíče a inicializaci vektoru (IV).
using (AesCryptoServiceProvider myAes = new AesCryptoServiceProvider())
Stránka 16
{
// Zde budeme šifrovat řetězec na pole bajtů
byte[] encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV);
// Dešifrování bajtů na řetězec
string roundtrip = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV);
//Zobrazení původního a dešifrovaného řetězce
Console.WriteLine("Original: {0}", original);
Console.WriteLine("Round Trip: {0}", roundtrip);
}
}
catch (Exception e)
{
Console.WriteLine("Error: {0}", e.Message);
}
finally
{
Console.ReadLine();
}
}
//Šifrování
internal static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
// Kontrola, zda argumenty jsou v pořádku
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
// Vytvoření nové instance AesCryptoServiceProvider class.
// Vytvoření nového klíče a inicializaci vektoru (IV).
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Vytvořte decrytor pro provedení proudu transformace.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Vytvoření proudů k šifrování
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor,
CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Zápis všech dat do proudu
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
Stránka 17
// Návrat šifrovaných bajtů
return encrypted;
}
//Dešifrování
internal static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
{
// Kontrola argumentů
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Deklarovat řetězec použitý k dešifrování textu
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Vytvoříme decrytor k provedení proudu transformace.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Vytvoříme prudy používané k dešifrování
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor,
CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Načteme dešifrované bajty a umístíme je do řetězce
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
}

CryptographicException -> Výjimkou která je vyvolána, když dojde k chybě během kryptografické operace.
Namespace System.Security.Permissions.
Hlavní třídy, které jsou použity v tomto jmenném prostoru.
 EnvironmentPermission -> Kontroly přístup k systému a uživatelských proměnných.
 FileDialogPermission -> Ovládá možnost přístupu k souborů a složekám pomocí souborového dialogu.
 FileIOPermission -> Ovládá možnost přístupu k souborům a složkám.
 IsolatedStorageFilePermission -> Určuje povolené použití soukromého virtuálního souborového systému.
Stránka 18





IsolatedStoragePermission -> Představuje přístup ke generickým ojedinělých schopností skladování.
ReflectionPermission -> Kontroly přístupu k metadatům prostřednictvím System.Reflection (API).
RegistryPermission -> Ovládá možnost přístupu k proměnné registru.
SecurityPermission -> Popisuje sadu bezpečnostních oprávnění aplikovaných na kód.
UIPermission -> Řídí oprávnění týkající se uživatelských rozhraní a schránky.
Důležité třídy v jiných jmených prostorech.
Namespace System.Net.
 WebPermission -> Určuje práva pro přístup k prostředkům v síti Internet pro protokol HTTP.
 SocketPermission -> Ovládací oprávnění pro příjem připojení na přepravní adresu.
 DnsPermission -> Ovládací prvky a jejich oprávnění pro přístup k serverům systému DNS (Domain Name) v
síti.
 DnsPermissionAttribute -> Určuje oprávnění požadovat informace od Domain Name serverů.
Příklad 14.
Příklad používá DnsPermissionAttribute deklarativní zabezpečení použítí vlastní třídy.
//Používá DnsPermissionAttribute omezit přístup pouze pro ty, kteří mají oprávnění.
[DnsPermission(SecurityAction.Demand, Unrestricted = true)]
public class MyClass
{
public static IPAddress GetIPAddress()
{
IPAddress ipAddress = Dns.Resolve("localhost").AddressList[0];
return ipAddress;
}
public static void Main(){
try{
//vybraný přístup
Console.WriteLine(" Access granted\n The local host IP Address is :" +
MyClass.GetIPAddress().ToString());
}
// odepřený přístup
catch(SecurityException securityException)
{
Console.WriteLine("Přístup zamítnut");
Console.WriteLine(securityException.ToString());
}
}
Namespace System.Data.SqlClient.

SqlClientPermission -> Umožňuje zprostředkovateli dat .NET Framework pro SQL server pomáhat. Uživatel
má úroveň zabezpečení dostatečné pro přístup ke zdroji dat.
Namespace System.Diagnostics.

PerformanceCounterPermission -> Umožňuje řídit přístupová oprávnění kód pro PerformanceCounter.
Stránka 19
Code Access Security Policy Tool - caspol.exe
Nástroj zásady zabezpečení přístupu kódu umožňuje uživatelům a správcům změnit bezpečnostní politiku na úroveň
stroje politik, uživatelské úrovni politiky a podnikové úrovni politiky. Naleznete v dokumentaci MSDN pro další
informace.
Možnost použití pro administrátory sítí. Mnoho možností pro SecurityRuleSet.Level2 je vynecháno.
Ochrana zdrojového kódu .NET.
Zpětné získání zdrojového kódu u aplikací .NET Framework je snadné na příklad nástrojem
JetBrains dotPeek 1.2 který je zdarma na trhu. Visual Studio 2013 dodává nástroj, který je přímo integrován
a to PreEmptive Dotfuscator v menu Nástroje. Tento nástroj nepředstavuje špičku, ale je zdarma.
Tyto nástroje patří ke zmatení zdrojového kódu a zamezí možnost zpětného překladu.
Popis není součástí této ukázky.
Ukázka použití je na příklad na webu :
http://www.dirkstrauss.com/visual-studio-2012/visual-studio-2012-tips-part-5-protect-your-code-obfuscate
nebo na : http://www.dotnetportal.cz/clanek/193/Ochrana-NET-aplikaci od pana Ondřeje Linharta.
Pár slov k manifestu:
Aplikace bude běžet ve stejném procesu jako ten, který tuto aplikaci spustil.
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
Aplikace se spustí s oprávněním správce. Uživatel musí být ve skupině administrators.
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
Aplikace bude běžet na nevyšší úrovni oprávnění. Pokud uživatel, který spustí aplikaci je členem skupiny
administrators, tato možnost je stejná jako requireAdministrator. V případě, že nejvyšší úroveň oprávnění k dispozici
je vyšší než úroveň procesu spuštění aplikace, systém vyzve k zadání pověření.
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
Stránka 20

Podobné dokumenty

kapitola 18

kapitola 18 Nepotřebná oprávnění odmítněte V zájmu principů nejmenších možných oprávnění je vhodné odmítnout oprávnění, která nepotřebujeme, i když nám je třeba běhová knihovna udělí. Pokud například daná apli...

Více