Programování

Zabezpečení a architektura zavaděče tříd

Předchozí 1 2 Strana 2 Stránka 2 ze 2

Zavaděče tříd a mezery

Pro každou třídu, kterou načte, JVM sleduje, který zavaděč třídy - ať už prvotní nebo objekt - načetl třídu. Když načtená třída nejprve odkazuje na jinou třídu, virtuální počítač požaduje odkazovanou třídu ze stejného zavaděče třídy, který původně načetl odkazující třídu. Například pokud virtuální stroj načte třídu Sopka prostřednictvím konkrétního zavaděče tříd se pokusí načíst jakékoli třídy Sopka odkazuje na přes stejný zavaděč třídy. Li Sopka odkazuje na třídu s názvem Láva, snad vyvoláním metody ve třídě Láva, virtuální stroj si vyžádá Láva z načítače třídy, který se načetl Sopka. The Láva třída vrácená zavaděčem třídy je dynamicky propojena s třídou Sopka.

Protože JVM používá tento přístup k načítání tříd, mohou třídy ve výchozím nastavení vidět pouze jiné třídy, které byly načteny stejným zavaděčem tříd. Tímto způsobem vám architektura Java umožňuje vytvořit více jmenné prostory uvnitř jedné aplikace Java. Prostor jmen je sada jedinečných názvů tříd načtených konkrétním zavaděčem tříd. Pro každý zavaděč tříd udržuje JVM jmenný prostor, který je vyplněn jmény všech tříd, které byly načteny prostřednictvím tohoto zavaděče tříd.

Jakmile JVM načte třídu s názvem Sopka například do konkrétního prostoru jmen nelze načíst jinou pojmenovanou třídu Sopka do stejného prostoru jmen. Můžete načíst více Sopka třídy do JVM, protože v aplikaci Java můžete vytvořit více prostorů jmen. Můžete tak učinit jednoduše vytvořením více zavaděčů tříd. Pokud vytvoříte tři oddělené prostory jmen (jeden pro každý ze tří zavaděčů třídy) ve spuštěné aplikaci Java, pak načtením jednoho Sopka třídy do každého prostoru jmen, váš program mohl načíst tři různé Sopka třídy do vaší aplikace.

Aplikace Java může vytvořit instanci více objektů zavaděče tříd buď ze stejné třídy, nebo z více tříd. Může tedy vytvářet tolik (a tolik různých druhů) objektů pro načítání tříd, kolik potřebuje. Třídy načtené různými zavaděči tříd jsou v různých prostorech jmen a nemohou k sobě navzájem získat přístup, pokud to aplikace výslovně neumožňuje. Když píšete aplikaci Java, můžete oddělit třídy načtené z různých zdrojů do různých prostorů jmen. Tímto způsobem můžete pomocí architektury zavaděče tříd Java ovládat jakoukoli interakci mezi kódem načteným z různých zdrojů. Můžete zabránit nepřátelskému kódu v získání přístupu k podvrácení přátelského kódu.

Zavaděče tříd pro applety

Jedním z příkladů dynamického rozšíření pomocí zavaděčů tříd je webový prohlížeč, který používá objekty zavaděče tříd ke stahování souborů tříd pro applet v síti. Webový prohlížeč vypálí aplikaci Java, která nainstaluje objekt zavaděče tříd - obvykle se nazývá zavaděč třídy appletů - to ví, jak požadovat soubory třídy ze serveru HTTP. Příkladem dynamického rozšíření jsou applety, protože při spuštění aplikace Java neví, které soubory třídy jej prohlížeč požádá o stažení přes síť. Soubory třídy ke stažení jsou určeny za běhu, protože prohlížeč narazí na stránky, které obsahují applety Java.

Aplikace Java spuštěná webovým prohlížečem obvykle vytváří jiný objekt zavaděče tříd appletů pro každé umístění v síti, ze kterého načítá soubory tříd. Výsledkem je, že soubory třídy z různých zdrojů jsou načteny různými objekty zavaděče tříd. Toto je umístí do různých prostorů jmen uvnitř hostitelské aplikace Java. Protože soubory třídy pro applety z různých zdrojů jsou umístěny v samostatných prostorech jmen, kód škodlivého appletu je omezen v přímém zasahování do souborů třídy stažených z jiného zdroje.

Spolupráce mezi třídními nakladači

Objekt zavaděče tříd se často spoléhá na jiné zavaděče tříd - přinejmenším na prvotní zavaděč tříd - aby mu pomohl splnit některé požadavky na načítání tříd, které se mu dostanou do cesty. Představte si například, že píšete aplikaci Java, která nainstaluje zavaděč tříd, jehož konkrétního způsobu načítání souborů tříd je dosaženo jejich stažením přes síť. Předpokládejme, že v průběhu běhu aplikace Java je od vašeho zavaděče tříd učiněn požadavek na načtení třídy s názvem Sopka.

Jedním ze způsobů, jak můžete napsat zavaděč tříd, je nechat ho nejprve požádat zavaděče prvotních tříd, aby našel a načetl třídu ze svého důvěryhodného úložiště. V tomto případě od Sopka není součástí Java API, předpokládejme, že zavaděč prvotních tříd nemůže najít třídu s názvem Sopka. Když zavaděč prvotních tříd odpoví, že nemůže načíst třídu, mohl by se váš zavaděč tříd pokusit načíst Sopka třídou svým vlastním způsobem stažením přes síť. Za předpokladu, že váš třídní zavaděč dokázal třídu stáhnout Sopka, že Sopka třída by pak mohla hrát roli v budoucím průběhu provádění aplikace.

Chcete-li pokračovat ve stejném příkladu, předpokládejme, že o nějaký čas později metoda třídy Sopka je vyvolána poprvé a že metoda odkazuje na třídu Tětiva z Java API. Protože je to poprvé, co je odkaz spuštěným programem použit, virtuální počítač se zeptá vašeho zavaděče tříd (ten, který se načetl Sopka) naložit Tětiva. Stejně jako dříve váš zavaděč tříd nejprve předá požadavek zavaděči prvotních tříd, ale v tomto případě je zavaděč prvotřídních tříd schopen vrátit Tětiva třídy zpět do vašeho třídního zavaděče.

Nakladač prvotní třídy se pravděpodobně nemusel skutečně načítat Tětiva v tomto bodě, protože vzhledem k tomu Tětiva je taková základní třída v programech Java, byla téměř jistě použita dříve, a proto již načtena. Nakladač prvotní třídy s největší pravděpodobností právě vrátil Tětiva třída, kterou předtím načetl z důvěryhodného úložiště.

Vzhledem k tomu, že prvotní zavaděč tříd byl schopen tuto třídu najít, váš zavaděč tříd se nepokouší stáhnout ji přes síť; pouze předá virtuálnímu stroji Tětiva třída vrácená zavaděčem prvotní třídy. Od té chvíle to virtuální stroj používá Tětiva třída kdykoli třída Sopka odkazuje na třídu s názvem Tětiva.

Nakladače tříd v karanténě

V sandboxu prostředí Java je architektura zavaděče tříd první linií obrany proti škodlivému kódu. Nakonec je to zavaděč tříd, který přináší kód do JVM - kód, který by mohl být nepřátelský.

Architektura zavaděče tříd přispívá do karantény prostředí Java dvěma způsoby:

  1. Zabraňuje tomu, aby škodlivý kód zasahoval do benevolentního kódu.
  2. Hlídá hranice důvěryhodných třídních knihoven.

Architektura zavaděče tříd chrání hranice důvěryhodných knihoven tříd tím, že zajišťuje, aby nedůvěryhodné třídy nemohly předstírat důvěryhodnost. Pokud by škodlivá třída mohla úspěšně přimět JVM, aby věřila, že jde o důvěryhodnou třídu z Java API, mohla by tato škodlivá třída potenciálně prorazit bariéru karantény. Tím, že brání nedůvěryhodným třídám v zosobnění důvěryhodných tříd, blokuje architektura zavaděče tříd jeden potenciální přístup ke kompromisu zabezpečení prostředí runtime Java.

Prostory jmen a štíty

Architektura zavaděče tříd brání škodlivému kódu v narušení benevolentního kódu poskytnutím chráněných prostorů jmen pro třídy načtené různými zavaděči tříd. Jak je zmíněno výše, jmenný prostor je sada jedinečných jmen pro načtené třídy, které udržuje JVM.

Prostory jmen přispívají k zabezpečení, protože ve skutečnosti můžete umístit štít mezi třídy načtené do různých prostorů jmen. Uvnitř JVM mohou třídy ve stejném prostoru jmen přímo interagovat. Třídy v různých prostorech jmen však nemohou ani navzájem detekovat přítomnost, pokud výslovně neposkytnete mechanismus, který umožňuje třídám komunikovat. Pokud by škodlivá třída, jakmile byla načtena, měla zaručený přístup ke každé další třídě, která je aktuálně načtena virtuálním strojem, mohla by se tato třída potenciálně naučit věci, které by neměla vědět, nebo by mohla narušit správné spuštění vašeho programu.

Vytváření bezpečného prostředí

Když píšete aplikaci, která používá zavaděče tříd, vytvoříte prostředí, ve kterém běží dynamicky načtený kód. Pokud chcete, aby prostředí neobsahovalo bezpečnostní díry, musíte při psaní zavaděčů aplikací a tříd dodržovat určitá pravidla. Obecně budete chtít napsat svou aplikaci tak, aby byl škodlivý kód chráněn před benevolentním kódem. Také budete chtít psát zavaděče tříd tak, aby chránily hranice důvěryhodných třídních knihoven, jako jsou rozhraní Java API.

Prostory jmen a zdroje kódu

Chcete-li získat výhody zabezpečení nabízené jmennými prostory, musíte se ujistit, že načítáte třídy z různých zdrojů prostřednictvím různých zavaděčů tříd. Toto je výše popsané schéma používané webovými prohlížeči s podporou Java. Aplikace Java vypálená webovým prohlížečem obvykle vytváří jiný objekt zavaděče tříd appletů pro každý zdroj tříd, který stáhne přes síť. Například prohlížeč by použil jeden objekt zavaděče tříd ke stažení tříd z //www.niceapplets.com a jiný objekt zavaděče tříd ke stažení tříd z //www.meanapplets.com.

Hlídání omezených balíčků

Java umožňuje třídám ve stejném balíčku navzájem si udělit zvláštní přístupová oprávnění, která nejsou udělena třídám mimo balíček. Pokud tedy váš zavaděč tříd obdrží požadavek na načtení třídy, která se svým jménem bezostyšně prohlašuje za součást Java API (například třída s názvem java.lang.Virus), měl by váš zavaděč tříd postupovat opatrně. Pokud by byla načtena, mohla by taková třída získat speciální přístup k důvěryhodným třídám java.lang a mohl by tento speciální přístup použít k podvodným účelům.

V důsledku toho byste normálně napsali zavaděč tříd, takže jednoduše odmítne načíst jakoukoli třídu, která tvrdí, že je součástí Java API (nebo jiné důvěryhodné běhové knihovny), ale která v místním důvěryhodném úložišti neexistuje. Jinými slovy, poté, co váš zavaděč třídy předá požadavek zavaděči prvotních tříd a zavaděč prvotních tříd naznačuje, že nemůže načíst třídu, měl by váš zavaděč tříd zkontrolovat, zda se třída nedeklaruje jako člen důvěryhodného balíčku. Pokud ano, měl by váš zavaděč třídy namísto pokusu o stažení třídy v síti vyvolat bezpečnostní výjimku.

Hlídání zakázaných balíků

Kromě toho můžete mít nainstalované některé balíčky v důvěryhodném úložišti, které obsahují třídy, které chcete, aby vaše aplikace mohla načíst prostřednictvím prvotního zavaděče tříd, ale že nechcete být přístupné pro třídy načtené pomocí vašeho zavaděče tříd. Předpokládejme například, že jste vytvořili balíček s názvem absolutní moc a nainstaloval jej do místního úložiště přístupného zavaděčem prvotních tříd. Předpokládejme také, že nechcete, aby třídy načtené vaším zavaděčem tříd mohly načíst jakoukoli třídu z absolutní moc balík. V tomto případě byste napsali svůj zavaděč tříd tak, že první věc, kterou udělá, je zajistit, aby se požadovaná třída nedeklarovala jako člen absolutní moc balík. Pokud je taková třída požadována, měl by váš třídní zavaděč namísto předání názvu třídy do prvotního zavaděče tříd vyvolat bezpečnostní výjimku.

Jediný způsob, jak zavaděč tříd může vědět, zda je třída z omezeného balíčku, například java.lang, nebo zakázaný balíček, jako je absolutní moc, je jménem třídy. Tedy zavaděč tříd musí dostat seznam názvů omezených a zakázaných balíčků. Protože název třídy java.lang.Virus označuje, že je z java.lang balíček a java.lang je na seznamu omezených balíčků, měl by váš zavaděč tříd vyvolat bezpečnostní výjimku, pokud jej zavaděč prvotní třídy nemůže načíst. Stejně tak proto, že název třídy absolutepower.FancyClassLoader označuje, že je součástí absolutní moc balíček a absolutní moc balíček je na seznamu zakázaných balíků, měl by váš zavaděč tříd vyvolat bezpečnostní výjimku.

Zavaděč tříd se zaměřením na zabezpečení

Běžným způsobem, jak napsat zavaděč tříd se zaměřením na zabezpečení, je použití následujících čtyř kroků:

  1. Pokud existují balíčky, ze kterých tento zavaděč tříd nemá povoleno načíst, zavaděč tříd ověří, zda je požadovaná třída v jednom z výše uvedených zakázaných balíčků. Pokud ano, vyvolá bezpečnostní výjimku. Pokud ne, pokračuje krokem dva.

  2. Zavaděč tříd předá požadavek prvotnímu zavaděči tříd. Pokud zavaděč prvotních tříd úspěšně vrátí třídu, vrátí zavaděč tříd stejnou třídu. Jinak pokračuje krokem tři.

  3. Pokud existují důvěryhodné balíčky, do kterých tento zavaděč tříd nemá povoleno přidávat třídy, zavaděč tříd ověří, zda je požadovaná třída v jednom z těchto omezených balíčků. Pokud ano, vyvolá bezpečnostní výjimku. Pokud ne, pokračuje krokem čtyři.

  4. Nakonec se zavaděč tříd pokusí načíst třídu vlastním způsobem, například stažením přes síť. Pokud bude úspěšný, vrátí třídu. Pokud je neúspěšné, vyvolá chybu „nebyla nalezena žádná definice třídy“.

Provedením kroků jedna a tři, jak je uvedeno výše, zavaděč třídy chrání hranice důvěryhodných balíčků. V prvním kroku brání tomu, aby se třída ze zakázaného balíčku vůbec načetla. V třetím kroku neumožňuje nedůvěryhodné třídě vložit se do důvěryhodného balíčku.

Závěr

Architektura zavaděče tříd přispívá k modelu zabezpečení JVM dvěma způsoby:

  1. oddělením kódu do více jmenných prostorů a umístěním „štítu“ mezi kód do různých jmenných prostorů
  2. hlídáním hranic důvěryhodných třídních knihoven, jako je Java API

Obě tyto schopnosti architektury zavaděče tříd Java musí programátoři správně používat, aby mohli těžit z výhod zabezpečení, které nabízejí. Chcete-li využít štít jmenného prostoru, kód z různých zdrojů by měl být načten prostřednictvím různých objektů zavaděče tříd. Aby bylo možné využít výhod důvěryhodného pohraničního zabezpečení balíčků, musí být napsány zavaděče tříd, aby zkontrolovaly názvy požadovaných tříd oproti seznamu omezených a zakázaných balíčků.

Prohlídku procesu psaní zavaděče tříd, včetně ukázkového kódu, najdete v článku Chucka McManise JavaWorld článek „Základy zavaděčů tříd Java.“

Příští měsíc

V článku příštího měsíce budu pokračovat v diskusi o bezpečnostním modelu JVM popisem ověřovatele třídy.

Bill Venners píše software profesionálně již 12 let. Se sídlem v Silicon Valley poskytuje softwarové poradenství a školení pod názvem Artima Software Company. V průběhu let vyvinul software pro spotřební elektroniku, vzdělávání, polovodiče a odvětví životního pojištění. Programoval v mnoha jazycích na mnoha platformách: montážní jazyk na různých mikroprocesorech, C na Unixu, C ++ na Windows, Java na webu. Je autorem knihy: Inside the Java Virtual Machine, vydané nakladatelstvím McGraw-Hill.

Další informace o tomto tématu

  • Kniha Specifikace virtuálního stroje Java (//www.aw.com/cp/lindholm-yellin.html), Tim Lindholm a Frank Yellin (ISBN 0-201-63452-X), součást The Java Series (//www.aw.com/cp /javaseries.html), z Addison-Wesley, je definitivní odkaz na virtuální stroj Java.
  • Zabezpečené výpočty pomocí JavaNow a budoucnosti (bílá kniha) // www.javasoft.com/marketing/collateral/security.html
  • Časté dotazy k zabezpečení appletu

    //www.javasoft.com/sfaq/

  • Nízká úroveň zabezpečení v Javě, autor Frank Yellin //www.javasoft.com/sfaq/verifier.html
  • Domovská stránka zabezpečení Java

    //www.javasoft.com/security/

  • Podívejte se na domovskou stránku nepřátelských appletů

    //www.math.gatech.edu/~mladue/HostileApplets.html

  • Kniha Zabezpečení Java Nepřátelské applety, díry a protilátky Gary McGraw a Ed Felton, podávají důkladnou analýzu bezpečnostních problémů kolem Javy. //www.rstcorp.com/java-security.html
  • Předchozí články „Under the Hood“:
  • Lean, Mean Virtual Machine - Představuje úvod do virtuálního stroje Java.
  • Životní styl souboru třídy Java - Poskytuje přehled souboru třídy Java, formátu souboru, do kterého jsou kompilovány všechny programy Java.
  • Java's Garbage- Collected Heap - Poskytuje přehled sběru odpadu obecně a hromady odpadu virtuálního stroje Java, zejména.
  • Základy Bytecode - Představuje bytové kódy virtuálního stroje Java a popisuje zejména primitivní typy, operace převodu a operace zásobníku.
  • Aritmetika s plovoucí desetinnou čárkou - popisuje podporu plovoucí desetinné čárky virtuálního počítače Java a bajtové kódy, které provádějí operace s plovoucí desetinnou čárkou.
  • Logic and Arithmetic - Describes the Java virtual machine's support for logical and integer arithmetic, and the related bytecodes.
  • Objekty a pole - popisuje, jak virtuální stroj Java pracuje s objekty a poli, a popisuje příslušné bytecodes.
  • Výjimky - popisuje, jak virtuální stroj Java pracuje s výjimkami, a popisuje příslušné bajtkódy.
  • Try-Finally - Popisuje, jak virtuální stroj Java implementuje klauzule try-finally, a popisuje příslušné bytecodes.
  • Řídicí tok - popisuje, jak virtuální stroj Java implementuje řídicí tok, a popisuje příslušné bajtkódy.
  • Architektura agletů - popisuje vnitřní fungování agletů, autonomní technologie softwarového agenta založené na Javě od IBM.
  • Point of Aglets - Analyzuje skutečnou užitečnost mobilních agentů, jako jsou aglety, autonomní technologie softwarových agentů založené na Javě od IBM.
  • Vyvolání a vrácení metody - popisuje čtyři způsoby, jak virtuální stroj Java vyvolá metody, včetně příslušných bajtových kódů.
  • Synchronizace vláken - Ukazuje, jak synchronizace vláken funguje na virtuálním stroji Java. Diskutuje o bytových kódech pro vstup a výstup z monitorů.
  • Java's Architecture Architecture - Poskytuje přehled bezpečnostního modelu zabudovaného do JVM a zkoumá vestavěné bezpečnostní prvky JVM.

Tento příběh „Zabezpečení a architektura zavaděče tříd“ původně publikoval JavaWorld.