LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> 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 16508×

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

pridej.cz

 

DISKUZE

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ů

17.4.2018 0:46 /František Kučera
Dubnový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 4. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tématem tohoto srazu bude OpenStreetMap (OSM) aneb svobodné mapy.
Přidat komentář

16.3.2018 22:01 /František Kučera
Kulatý OpenAlt sraz v Praze oslavíme klasicky: u limonády a piva! Přijďte si posedět, dát si dobré jídlo a vybrat z mnoha piv do restaurace Kulový blesk, který najdete v centru Prahy nedaleko metra I. P. Pavlova na adrese Sokolská 13, Praha 2. Sraz se koná ve čtvrtek 22. března a začínáme v 18:00. Heslo: OpenAlt. Vezměte s sebou svoje hračky! Uvítáme, když si s sebou na sraz vezmete svoje oblíbené hračky. Jestli máte nějaký drobný projekt postavený na Arduinu, nějakou zajímavou elektronickou součástku, či třeba i pěkný úlovek z crowdfundingové akce, neváhejte. Oslníte ostatní a o zábavu bude postaráno.
Přidat komentář

13.2.2018 0:41 /František Kučera
Únorový pražský sraz OpenAltu se koná 15. 2. 2018 a tentokrát se vydáme na návštěvu do jednoho pražského datacentra. Sejdeme se v 17:50 v severovýchodní části nástupiště tramvajové zastávky Koh-I-Noor. Po exkurzi se přesuneme do restaurace U Pštrosa (Moskevská 49), kde probereme tradiční témata (svobodný software a hardware, DIY, CNC, SDR, 3D tisk…) a tentokrát bude k vidění i IoT brána od The Things Network.
Přidat komentář

11.2.2018 23:11 /Petr Ježek
Hledáte lehký a rychlý prolížeč PDF souborů? Pokud vás již omrzelo čekat na načítání stránek či jiné nešvary, zkuste xreader.
Přidat komentář

11.2.2018 20:35 /Redakce Linuxsoft.cz
Třetí ročník odborné IT konference na téma Cloud computing v praxi proběhne ve čtvrtek 1. března 2018 v konferenčním centru Vavruška, v paláci Charitas, Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00 hod. dopoledne do cca 16 hod. odpoledne. Konference o trendech v oblasti cloud computingu nabídne i informace o konkrétních možnostech využívání cloudů a řešení vybraných otázek souvisejících s provozem IT infrastruktury.
Přidat komentář

15.1.2018 0:51 /František Kučera
První letošní pražský sraz se koná již tento čtvrtek 18. ledna od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Vítáni jsou všichni příznivci svobodného softwaru a hardwaru, ESP32, DIY, CNC, SDR nebo dobrého piva. Prvních deset účastníků srazu obdrží samolepku There Is No Cloud… just other people's computers. od Free Software Foundation.
Přidat komentář

14.11.2017 16:56 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tradičně první čtvrtek před třetím pátkem v měsíci: 16. listopadu od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.11.2017 11:06 /Redakce Linuxsoft.cz
PR: 4. ročník odborné IT konference na téma Datová centra pro business proběhne již ve čtvrtek 23. listopadu 2017 v konferenčním centru Vavruška, v paláci Charitas, Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00. Konference o návrhu, budování, správě a efektivním využívání datových center nabídne odpovědi na aktuální a často řešené otázky, např Jaké jsou aktuální trendy v oblasti datových center a jak je využít pro vlastní prospěch? Jak zajistit pro firmu či jinou organizaci odpovídající služby datových center? Podle jakých kritérií vybrat dodavatele služeb? Jak volit součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně spravovat datové centrum? Jak eliminovat možná rizika? apod.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

20.2.2018 18:48 / Ivan Majer
portal

20.2.2018 15:57 / Jan Havel
Jak využíváte služby cloudu v podnikání?

16.1.2018 1:08 / Ivan Pittner
verejna ip od o2 ubuntu

15.1.2018 17:26 / Mira Harvalik
Re: Jak udělat HTML/Javascript swiping gallery do mobilu?

30.12.2017 20:16 / Michal Knoll
odmocnina

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2018) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze