Java (22) - omezování práv I.
Minule jsme načítali objektové třídy za běhu programu. To je činnost
potenciálně velmi nebezpečná, proto je žádoucí (nejen) v takovém případě omezit
práva kódu získanému zvnějšku. Podívejme se, jak se to dělá.
30.1.2006 06:00 |
Lukáš Jelínek
| Články autora
| přečteno 19428×
Bezpečnost především
Spustíme-li normální javovskou aplikaci, běží ve výchozím nastavení
s maximálními právy. Veškerý obsažený kód má tedy právo dělat si v systému
cokoliv (samozřejmě s ohledem na práva v operačním systému). V minulém dílu
seriálu jsme načítali třídy za běhu programu, vytvářeli instance těchto tříd
a spouštěli je. Co by se stalo, kdyby nám někdo zlomyslně podstrčil třídu,
která by obsahovala nějaký škodlivý kód? Odpověď je jasná - záleželo by pouze
na tvůrci programu, jaké "potěšení" by nám připravil. Systém mu je zcela
k dispozici a může tedy zcela nerušeně třeba smazat obsah domovského adresáře.
Základním pravidlem je absolutní nedůvěra ke kódu získanému odněkud zvenku
(z webového serveru apod.). Kód zkrátka nesmí mít možnost něco zlého provést.
A jak mu tuto možnost odejmout, na to se nyní podíváme.
Hlídač v systému
K vynucení bezpečnostních omezení si přizveme na pomoc "hlídače" (budeme pro
něj používat termín security manager). Hlídač bude schvalovat všechny
potenciálně nebezpečné operace, a povolí jen takové, které budou odpovídat
určeným bezpečnostním pravidlům.
Hlídač je v Javě představován třídou java.lang.SecurityManager . V rámci jedné
JVM může být aktivní pouze jediný security manager - můžeme ho nastavit už
při spouštění programu v příkazové řádce, anebo i za běhu programu. Pozor
ovšem, že i nastavení nového security managera je schvalovanou operací, ten
stávající "hlídač" to tedy musí povolit.
Lze používat přímo třídu SecurityManager , nebo si vytvořit jejího potomka a
dodat mu potřebné vlastnosti. Hlavně ale můžeme používat ještě silnější
a univerzálnější řešení (kde ani není potřeba mít explicitně vytvořeného
security managera) - brzy se k němu dostaneme.
Povolení ... máš?
Termín "povolení" (permission) je dalším z pojmů, které nás velice zajímají.
Zde ho představuje třída java.security.Permission , ale v tomto případě to není
tak, že by tento objekt znamenal přímo oprávnění provést nějakou akci. Naopak,
pomocí instance třídy Permission se dotazujeme security managera, zda
tímto povolením disponujeme.
Mezi potomky třídy Permission existují důležité vztahy. Některá povolení totiž
mohou implikovat jiná. Např. třída AllPermission implikuje všechna ostatní
povolení, proto je-li schváleno toto povolení, schválí se i jakákoli
jiná. Jiným příkladem je povolení ke čtení všech souborů v kořenovém adresáři,
implikující všechna povolení číst soubory kdekoli ve stromě. Potomci třídy
Permission nejsou (narozdíl od většiny věcí souvisejících s bezpečností)
všichni umístěni v balíku java.security , ale nacházejí se v různých balících, podle
oblasti, které se týkají (jsou třeba v java.lang nebo java.net ).
Důležitou otázkou je, jak schválení probíhá. Třída SecurityManager má jednak
metody checkPermission() , a dále množství dalších metod začínajících slovem
check. Ty první jsou primární, druhé ve výchozí implementaci volají ty první
s patřičným objektem typu Permission . Chování lze samozřejmě v potomkovi
změnit. Všechny tyto metody (až na jedinou výjimku, metodu
checkTopLevelWindow() ) se ale navenek chovají shodně - je-li operace povolena,
metoda se tiše vykoná a běh normálně pokračuje dál. Když je ale operace
zamítnuta, vyvolá se výjimka java.lang.SecurityException .
Ještě dodám, že existují také třídy PermissionCollection a Permissions .
První z nich je abstraktní kolekce povolení, druhá pak její standardní
implementace. Umožňují práci s celou množinou povolení najednou (zejména
předávání jiným objektům), včetně zjišťování implikací.
Bezpečnostní model
Javovský bezpečnostní model je založen na doménách. Každá doména vlastní
povolení pro určitý rozsah operací (který je dán aktuálním nastavením
bezpečnostní politiky). Programový kód (třída, instance) nemůže získat vyšší
práva tím, že zavolá kód z jiné domény (ani tím, že je z této domény volán).
Domény se dělí do dvou kategorií - aplikační a systémové. Přístup k prostředkům
systému je povolen pouze v systémových doménách (běžně je pouze jediná).
Důležitou skutečností je, že při průchodu různými doménami má kód oprávnění
odpovídající jejich průniku - tedy jen ta oprávnění, která má ve všech doménách.
Protože by samozřejmě jakékoli omezení v celém řetězci volání bránilo
používat systémové prostředky a jiné potenciálně nebezpečné věci, existuje
řešení: označit nějaký kód jako privilegovaný. Jak se to dělá, k tomu se
vrátíme za chvíli.
Implicitní mechanismus kontroly
Původně (ve verzích JDK 1.0 a 1.1) byl bezpečnostní model jednoduchý a
přímočarý, což se s příchodem další verze změnilo. Nyní máme k dispozici
implicitní kontrolní mechanismus, který provádí kontrolu oprávnění
v případech, kdy se nepoužije přímo security manager. Poskytuje ho třída
java.security.AccessController , a kromě kontroly přístupu se stará také
o běh privilegovaného kódu a některé další činnosti. Od této třídy se netvoří
instance, všechny metody jsou statické.
Podívejme se na to, jak se to dělá v praxi. Máme kus kódu, který potřebuje
číst ze souboru /etc/passwd . Následující příklad ukazuje, jak by to vypadalo
v různých případech:
SecurityManager sm = System.getSecurityManager();
Permission p = new FilePermission("/etc/passwd", "read");
if (sm != null) {
sm.checkPermission(p);
sm.checkRead("/etc/passwd");
}
AccessController.checkPermission(p);
V příkladu jsou uvedeny tři cesty, jak se ověřují oprávnění. První je získání
aktuální instance security managera, vytvoření instance třídy FilePermission
(pro povolení číst příslušný soubor), a následná kontrola povolení
security managera. Ve druhém případě se volá přímo metoda checkRead() se
stejnými parametry, což provede naprosto totéž. A konečně poslední cestou
je kontrola povolení u třídy AccessController . Tato třetí cesta je základní
metodou volby, a měla by se používat vždy, pokud není zvláštní důvod postupovat
jinak. Navíc metody třídy SecurityManager volají také stejnou metodu
třídy AccessController , pokud nejsou v potomkovi předefinovány.
Hlavní výhodou tohoto postupu je, že se nemusí nic zvláštního programovat.
Všechno máme k dispozici, a záleží pak na nastavení bezpečnostní politiky,
co všechno kódu umožníme provádět.
Privilegovaný kód
Kus kódu, který by se měl provádět se zvláštní úrovní oprávnění (s vyšší, než
by odpovídalo příslušným bezpečnostním doménám), je nutné označit jako
privilegovaný. Dělá se to typicky javovským způsobem - tedy vytvořením
instance implementace rozhraní PrivilegedAction a předáním metodě
AccessController.doPrivileged (), která zajistí provedení s příslušnými právy.
Pokud je nutné vyhazovat synchronní výjimku, použije se implementace rozhraní
PrivilegedExceptionAction .
Privilegovaný kód poběží s oprávněním domény, ze které byl přímo zavolán
- předchozí domény v řetězci volání se neberou v úvahu.
Použití přiblíží příklad:
PrivilegedAction<Boolean> pa = new PrivilegedAction<Boolean>() {
public Boolean run() {
try {
System.loadLibrary("mylibrary");
return new Boolean(true);
} catch (Throwable e) { // musíme chytit i UnsatisfiedLinkError
return new Boolean(false);
}
}
};
if (AccessController.doPrivileged(pa).booleanValue()) {
... // nějaký kód závislý na načtení knihovny
}
Příklad ukazuje načtení knihovny do systému použitím privilegovaného kódu.
Vytvoří se instance anonymní třídy vzniklé implementací PrivilegedAction .
Metoda run() vykoná vše potřebné (všechny výjimky i chyby zde budeme zachycovat
uvnitř) a vrátí výsledek operace. K úspěšnému (z hlediska bezpečnosti)
provedení stačí, aby kód volající doPrivileged() patřil do domény disponující
povolením RuntimePermission pro akci "loadLibrary.mylibrary" .
Bezpečnostní kontext
Za normálních okolností se bezpečnostní kontroly vztahují ke vláknu, které
určitý kód provádí. To není vždy úplně nejvhodnější - někdy může být potřeba
poskytnout pro konkrétní účely vláknu jiná (typicky vyšší) oprávnění.
Proto existuje třída AccessControlContext , která představuje kontext pro
oprávnění vlákna. Její instanci vlákno získá zavoláním metody getContext()
třídy AccessController , a pak ji může předat jinému vláknu k dalšímu použití
(ve voláních checkPermission () a doPrivileged ()).
Asi bude nejlepší si to ukázat na příkladu. Máme dvě vlákna, jedno druhému
poskytne svůj kontext, a to ho použije ke kontrole oprávnění:
public class MyThread extends Thread {
private AccessControlContext ctx = null;
public void setContext(AccessControlContext ctx) {
this.ctx = ctx;
}
public void run() {
...
Permission p =
new SocketPermission("nejaka.adresa.com:12345", "connect");
try {
if (ctx != null)
ctx.checkPermission(p); // ověření povolení podle kontextu
else
AccessController.checkPermission(p); // není nenastaven kontext
... // právo pro přístup do sítě
} catch (SecurityException e) {
... // zákaz přístupu do sítě
}
...
}
}
...
MyThread t = getWorkerThread(); // získání přístupu k pracovnímu vláknu
t.setContext(AccessController.getContext());
...
Máme vlákno, které vykonává nějaké služební činnosti pro ostatní vlákna.
Během této činnosti se potřebuje připojit někam do sítě, na což ovšem nemusí
mít oprávnění. Proto mu vlákno, které na využití služeb má zájem, poskytne
svůj kontext. Pokud v rámci tohoto kontextu existuje příslušné oprávnění,
je přístup do sítě umožněn, jinak nikoliv. Nezíská-li vlákno cizí kontext,
provede se ověření standardním způsobem. Příklad je samozřejmě velmi
jednoduchý a naivní, skutečná implementace by byla složitější.
Ještě důležitá poznámka - nově vytvořené vlákno dědí automaticky
bezpečnostní kontext svého rodiče. To znamená, že se ho týkají všechna omezení
daná doménami, kterými rodič prošel. Pokud by tomu tak nebylo, mohlo by to
znamenat nepříjemné riziko. Proto implementace vytváření vláken
zajišťuje, aby vlákno získalo bezpečnostní kontext od svého rodiče.
Ztělesnění domény
Byla řeč o bezpečnostních doménách - každý si tedy může klást otázku, jak
jsou tyto domény vyjádřeny. K tomu máme třídu java.security.ProtectionDomain ,
která obsahuje tzv. zdroj kódu (URL + případné certifikáty k ověření podpisu
kódu), zavaděč tříd, vlastnosti uživatele a staticky definovaná oprávnění
(nezávislá na aktuální bezpečnostní politice). Efektivní oprávnění domény
pak závisí samozřejmě na nastavení politiky.
K čemu je to dobré? Všimněte si zejména, že zde figuruje zavaděč tříd.
Právě ten totiž určuje, do které domény bude načtený kód patřit (a zkonstruuje
i instanci objektu domény). V závislosti na použitém zavaděči se tak může
- i pro stejný kód - velmi lišit množina oprávnění, kterou bude kód disponovat.
Jak omezit práva?
Dostali jsme se do bodu, kdy máme k dispozici celý aparát pro kontrolu
oprávnění, víme, jak pracuje, takže ještě zbývá určit, co komu povolíme.
Protože je to poměrně rozsáhlá záležitost, podíváme se na to příště. Budeme
se zabývat hlavně zavaděči tříd a nastavováním bezpečnostní politiky, ale
dostaneme se i k problematice podepisování kódu, což je další z metod
posilování bezpečnosti při současném zjednodušení práce.
Verze pro tisk
|
Nejsou žádné diskuzní příspěvky u dané položky.
Příspívat do diskuze mohou pouze registrovaní uživatelé.
|
|

Vyhledávání software

Vyhledávání článků
28.11.2018 23:56 /František Kučera Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1
12.11.2018 21:28 /Redakce Linuxsoft.cz 22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář
6.11.2018 2:04 /František Kučera Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
4.10.2018 21:30 /Ondřej Čečák LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář
18.9.2018 23:30 /František Kučera Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář
9.9.2018 14:15 /Redakce Linuxsoft.cz 20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business.
Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář
12.8.2018 16:58 /František Kučera Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář
16.7.2018 1:05 /František Kučera Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář
Více ...
Přidat zprávičku
 Poslední diskuze
31.7.2023 14:13 /
Linda Graham iPhone Services
30.11.2022 9:32 /
Kyle McDermott Hosting download unavailable
13.12.2018 10:57 /
Jan Mareš Re: zavináč
2.12.2018 23:56 /
František Kučera Sraz
5.10.2018 17:12 /
Jakub Kuljovsky Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?
Více ...
|