Ohjelmointi

Turvallisuus ja luokan latausarkkitehtuuri

Edellinen 1 2 Sivu 2 Sivu 2/2

Luokan kuormaajat ja nimivälit

Jokaisen lataamansa luokan kohdalla JVM seuraa, mikä luokan kuormaaja - olipa se alku- tai objekti - ladasi luokan. Kun ladattu luokka viittaa ensin toiseen luokkaan, virtuaalikone pyytää viitattua luokkaa samalta luokkakuormaajalta, joka alun perin latasi viittausluokan. Esimerkiksi, jos virtuaalikone lataa luokan Tulivuori tietyn luokan kuormaajan kautta se yrittää ladata kaikki luokat Tulivuori viittaa saman luokan kuormaajan kautta. Jos Tulivuori viittaa nimettyyn luokkaan Laava, ehkä käyttämällä menetelmää luokassa Laava, virtuaalikone pyytää Laava ladatusta luokan kuormaajasta Tulivuori. Laava luokan kuormaajan palauttama luokka on dynaamisesti linkitetty luokkaan Tulivuori.

Koska JVM käyttää tätä lähestymistapaa luokkien lataamiseen, luokat voivat oletusarvoisesti nähdä vain muut saman luokan kuormaajan lataamat luokat. Tällä tavalla Java-arkkitehtuurin avulla voit luoda useita nimivälit yhden Java-sovelluksen sisällä. Nimiavaruus on joukko yksilöllisiä nimien luokkia, jotka tietyn luokan kuormaaja lataa. JVM ylläpitää kutakin luokkakuormaajaa varten nimiavaruutta, joka täytetään kaikkien luokkakuormaajan kautta ladattujen luokkien nimillä.

Kun JVM on ladannut luokan nimeltä Tulivuori esimerkiksi tiettyyn nimiavaruuteen on mahdotonta ladata toista nimettyä luokkaa Tulivuori samaan nimitilaan. Voit ladata useita Tulivuori luokista JVM: ksi, koska voit luoda useita nimiavaruuksia Java-sovelluksen sisällä. Voit tehdä sen yksinkertaisesti luomalla useita luokan kuormaajia. Jos luot kolme erillistä nimitilaa (yhden kullekin kolmesta luokan lataajasta) käynnissä olevaan Java-sovellukseen, lataamalla yksi Tulivuori luokan jokaiseen nimiavaruuteen, ohjelmasi voisi ladata kolme erilaista Tulivuori luokat hakemukseesi.

Java-sovellus voi ilmentää useita luokan latausobjekteja joko samasta luokasta tai useista luokista. Siksi se voi luoda niin monta (ja niin monta erilaista) luokan kuormaajaobjektia kuin tarvitsee. Eri luokkakuormaajien lataamat luokat ovat eri nimiavaruuksissa, eivätkä ne pääse toisiinsa, ellei sovellus nimenomaisesti salli sitä. Kun kirjoitat Java-sovellusta, voit erottaa eri lähteistä ladatut luokat eri nimitiloihin. Tällä tavoin voit käyttää Javan luokan latausarkkitehtuuria hallitsemaan eri lähteistä ladattujen koodien välistä vuorovaikutusta. Voit estää vihamielistä koodia pääsemästä ystävälliseen koodiin ja hajottamasta sitä.

Luokkakuormaajat sovelmille

Yksi esimerkki dynaamisesta laajennuksesta luokkakuormaajilla on verkkoselain, joka käyttää luokan latausobjekteja lataamaan luokkatiedostot sovelmalle verkon kautta. Web-selain laukaisee Java-sovelluksen, joka asentaa luokan latausobjektin - jota yleensä kutsutaan applet-luokan kuormaaja - osaa pyytää luokkatiedostoja HTTP-palvelimelta. Appletit ovat esimerkki dynaamisesta laajennuksesta, koska kun Java-sovellus käynnistyy, se ei tiedä, minkä luokan tiedostot selain pyytää sitä lataamaan verkon yli. Ladattavat luokkatiedostot määritetään ajon aikana, kun selain kohtaa Java-sovelmia sisältäviä sivuja.

Web-selaimen käynnistämä Java-sovellus luo yleensä erilaisen applet-luokan latausobjektin kullekin verkon sijainnille, josta se hakee luokkatiedostot. Seurauksena on, että eri luokan latausobjektit lataavat luokkatiedostot eri lähteistä. Tämä sijoittaa ne eri nimitiloihin isäntä Java-sovelluksen sisällä. Koska eri lähteistä peräisin olevien sovelmien luokkatiedostot sijoitetaan erillisiin nimitiloihin, haitallisen sovelman koodi ei saa häiritä suoraan mistä tahansa muusta lähteestä ladattuja luokkatiedostoja.

Yhteys luokkakuormaajien välillä

Usein luokan kuormaajaobjekti luottaa muihin luokan kuormaajiin - ainakin primitiiviseen luokan kuormaajaan - auttamaan sitä täyttämään joitain tiensä luokan kuormituspyyntöjä. Kuvittele esimerkiksi, että kirjoitat Java-sovelluksen, joka asentaa luokan latauslaitteen, jonka luokkatiedostojen lataustapa saavutetaan lataamalla ne verkon kautta. Oletetaan, että Java-sovelluksen suorittamisen aikana luokan kuormaajasta pyydetään luokan nimistä lataamista Tulivuori.

Yksi tapa, jolla voit kirjoittaa luokan kuormaajan, on saada se ensin pyytämään alkuluokan latainta etsimään ja lataamaan luokka luotetusta arkistostaan. Tässä tapauksessa, koska Tulivuori ei ole osa Java-sovellusliittymää, oletetaan, että alkuluokan lataaja ei löydä luokkaa nimeltä Tulivuori. Kun alkuluokan kuormaaja vastaa, että se ei voi ladata luokkaa, luokan kuormaaja voi yrittää ladata sen Tulivuori luokka omalla tavallaan lataamalla se verkon kautta. Olettaen, että luokan kuormaaja pystyi lataamaan luokan Tulivuori, se Tulivuori luokka voisi sitten olla rooli sovelluksen tulevassa suorituksessa.

Jos haluat jatkaa samaa esimerkkiä, oletetaan, että jonkin aikaa myöhemmin menetelmä luokalle Tulivuori kutsutaan ensimmäistä kertaa ja että menetelmä viittaa luokkaan Merkkijono Java-sovellusliittymästä. Koska käynnissä oleva ohjelma käyttää viittausta ensimmäistä kertaa, virtuaalikone kysyy luokan lataajalta (lataajalta) Tulivuori) lastata Merkkijono. Kuten aiemmin, luokkakuormaajasi välittää pyynnön ensin perusluokan kuormaajalle, mutta tässä tapauksessa alkuluokan kuormaaja pystyy palauttamaan Merkkijono luokka takaisin luokan kuormaajaan.

Alkuperäisen luokan kuormaajan ei todennäköisesti tarvinnut ladata Merkkijono tässä vaiheessa, koska sen vuoksi Merkkijono on niin tärkeä Java-ohjelmien luokka, sitä käytettiin melkein varmasti aikaisemmin ja siksi se oli jo ladattu. Todennäköisesti alkuluokan kuormaaja vain palautti Merkkijono luokka, jonka se oli aiemmin ladannut luotetusta arkistosta.

Koska alkuluokan kuormaaja pystyi löytämään luokan, luokan kuormaaja ei yritä ladata sitä verkon kautta; se vain siirtää virtuaalikoneelle Merkkijono alkuluokan kuormaajan palauttama luokka. Siitä eteenpäin virtuaalikone käyttää sitä Merkkijono luokka aina luokassa Tulivuori viittaa nimettyyn luokkaan Merkkijono.

Luokan kuormaajat hiekkalaatikossa

Javan hiekkalaatikossa luokan latausarkkitehtuuri on ensimmäinen puolustuslinja haittaohjelmia vastaan. Juuri luokan kuormaaja tuo koodin JVM: ään - koodi, joka voi olla vihamielinen.

Luokan latausarkkitehtuuri tukee Java-hiekkalaatikkoa kahdella tavalla:

  1. Se estää haitallista koodia häiritsemästä hyväntahtoista koodia.
  2. Se vartioi luotettujen luokkakirjastojen rajoja.

Luokkakuormaajaarkkitehtuuri valvoo luotettujen luokkakirjastojen rajoja varmistamalla, että epäluotettavat luokat eivät voi teeskennellä olevansa luotettavia. Jos haitallinen luokka voisi onnistuneesti huijata JVM: n uskomaan, että se on luotettu luokka Java-sovellusliittymästä, se voi mahdollisesti murtautua hiekkalaatikon esteen läpi. Estämällä epäluotettavia luokkia esiintymästä luotettaviin luokkiin, luokan latausarkkitehtuuri estää yhden mahdollisen lähestymistavan Java-ajonaikaisen turvallisuuden vaarantamiseen.

Nimivälit ja kilvet

Luokkakuormaajaarkkitehtuuri estää haitallista koodia puuttumasta hyväntahtoiseen koodiin tarjoamalla suojatut nimitilat eri luokkakuormaajien lataamille luokille. Kuten yllä mainittu, nimitila on ladattujen luokkien yksilöllinen nimi, jota JVM ylläpitää.

Nimivälit lisäävät turvallisuutta, koska voit itse asiassa sijoittaa kilven eri nimitiloihin ladattujen luokkien väliin. JVM: n sisällä saman nimiavaruuden luokat voivat olla vuorovaikutuksessa suoraan keskenään. Eri nimivälissä olevat luokat eivät kuitenkaan edes tunnista toistensa läsnäoloa, ellet nimenomaisesti tarjoa mekanismia, joka sallii luokkien vuorovaikutuksen. Jos haitallinen luokka, kun se oli ladattu, takasi pääsyn kaikkiin muihin virtuaalikoneen tällä hetkellä lataamiin luokkiin, kyseinen luokka voisi mahdollisesti oppia asioita, joita sen ei pitäisi tietää, tai se voi häiritä ohjelman asianmukaista suorittamista.

Turvallisen ympäristön luominen

Kun kirjoitat luokan lataimia käyttävää sovellusta, luot ympäristön, jossa dynaamisesti ladattu koodi toimii. Jos haluat, että ympäristössä ei ole turva-aukkoja, sinun on noudatettava tiettyjä sääntöjä kirjoittaessasi sovellusta ja luokan kuormaajia. Yleensä sinun kannattaa kirjoittaa hakemuksesi siten, että haitallinen koodi on suojattu hyväntahtoiselta koodilta. Haluat myös kirjoittaa luokan kuormaajat siten, että ne suojaavat luotettujen luokkakirjastojen, kuten Java-sovellusliittymän, rajoja.

Nimivälit ja koodilähteet

Saadaksesi nimivälien tarjoamat tietoturvaedut, sinun on varmistettava, että lataat luokkia eri lähteistä eri luokkakuormaajien kautta. Tätä yllä kuvattua mallia käyttävät Java-yhteensopivat verkkoselaimet. Web-selaimen käynnistämä Java-sovellus luo yleensä erilaisen sovelmaluokan latausobjektin jokaiselle verkon kautta lataamalleen luokkalähteelle. Esimerkiksi selain käyttää yhtä luokan latausobjektia luokkien lataamiseen osoitteesta //www.niceapplets.com ja toista luokan latausobjektia luokkien lataamiseen osoitteesta //www.meanapplets.com.

Rajoitettujen pakettien vartiointi

Java sallii saman paketin luokkien myöntää toisilleen erityisiä käyttöoikeuksia, joita ei myönnetä paketin ulkopuolella oleville luokille. Joten, jos luokan kuormaaja saa pyynnön ladata luokka, joka julistaa itsensä räikeästi osaksi Java-sovellusliittymää (esimerkiksi luokan nimeltä java.lang.virus), luokan kuormaajan tulisi toimia varovaisesti. Jos tällainen luokka ladataan, se voi saada erityisen pääsyn luotettuihin luokkiin java.lang ja voisi mahdollisesti käyttää tätä erityistä pääsyä kavaliin tarkoituksiin.

Tämän vuoksi kirjoitat yleensä luokan lataimen niin, että se yksinkertaisesti kieltäytyy lataamasta luokkaa, joka väittää olevansa osa Java-sovellusliittymää (tai muuta luotettua ajonaikaisia ​​kirjastoja), mutta joita ei ole paikallisessa luotettavassa arkistossa. Toisin sanoen, kun luokkakuormaajasi välittää pyynnön alkuluokan kuormaajalle ja kun alkuluokan kuormaaja ilmoittaa, ettei se voi ladata luokkaa, luokan kuormaajan tulisi tarkistaa, ettei luokka ilmoita olevansa jäsen luotettavan paketin. Jos näin tapahtuu, luokan lataajan pitäisi heittää turvallisuuspoikkeus sen sijaan, että yrität ladata luokkaa verkkoon.

Kiellettyjen pakettien vartiointi

Lisäksi olet saattanut asentaa luotettuun arkistoon joitain paketteja, jotka sisältävät luokkia, joiden haluat sovelluksesi lataavan alkuluokan kuormaajan kautta, mutta joita et halua olla luokkakuormaajan kautta ladattujen luokkien käytettävissä. Oletetaan esimerkiksi, että olet luonut paketin nimeltä absoluuttinen voima ja asensi sen paikalliseen arkistoon, johon pääluokan lataaja pääsee. Oletetaan myös, että et halua, että luokkakuormaajasi lataamat luokat voivat ladata minkä tahansa luokan absoluuttinen voima paketti. Tässä tapauksessa kirjoitat luokan kuormaajasi siten, että ensimmäinen asia, jonka se tekee, on varmistaa, että pyydetty luokka ei ilmoita itseään jäseneksi absoluuttinen voima paketti. Jos tällaista luokkaa pyydetään, luokan kuormaajan tulisi heittää turvallisuuspoikkeus sen sijaan, että välittäisi luokan nimen alkuperäiseen luokan kuormaajaan.

Ainoa tapa, jolla luokan kuormaaja voi tietää, onko luokka peräisin rajoitetusta paketista, kuten java.langtai kielletty paketti, kuten absoluuttinen voima, on luokan nimellä. Siksi luokan kuormaajalle on annettava luettelo rajoitettujen ja kiellettyjen pakettien nimistä. Koska luokan nimi java.lang.virus osoittaa, että se on peräisin java.lang ja java.lang on rajoitettujen pakettien luettelossa, luokan kuormaajan tulisi heittää tietoturvapoikkeus, jos alkuperäinen luokan lataaja ei voi ladata sitä. Samoin, koska luokan nimi absolutepower.FancyClassLoader osoittaa, että se on osa absoluuttinen voima paketti ja absoluuttinen voima paketti on kiellettyjen pakettien luettelossa, luokan kuormaajan tulisi heittää suojauspoikkeus.

Turvallisuusmielinen luokan kuormaaja

Yleinen tapa kirjoittaa turvallisuusmielinen luokan lataaja on käyttää seuraavia neljää vaihetta:

  1. Jos on olemassa paketteja, joista tämän luokan kuormaajaa ei saa ladata, luokkakuormaaja tarkistaa, onko pyydetty luokka jossakin yllä mainituista kielletyistä paketeista. Jos näin on, se heittää tietoturvapoikkeuksen. Jos ei, se jatkuu vaiheeseen 2.

  2. Luokkakuormaaja välittää pyynnön alkuperäiselle luokan kuormaajalle. Jos alkuluokan kuormaaja palauttaa luokan onnistuneesti, luokan lataaja palauttaa saman luokan. Muuten se jatkuu vaiheeseen kolme.

  3. Jos luotettavia paketteja on olemassa, että tämän luokan kuormaaja ei saa lisätä luokkia, luokkakuormaaja tarkistaa, onko pyydetty luokka jossakin näistä rajoitetuista paketeista. Jos näin on, se heittää tietoturvapoikkeuksen. Jos ei, se jatkuu vaiheeseen neljä.

  4. Lopuksi luokan kuormaaja yrittää ladata luokan mukautetulla tavalla, esimerkiksi lataamalla sen verkon kautta. Jos se onnistuu, se palauttaa luokan. Jos se epäonnistuu, se heittää virheilmoituksen "luokan luokkaa ei löydy".

Suorittamalla vaiheet yksi ja kolme yllä esitetyllä tavalla, luokan kuormaaja vartioi luotettavien pakettien rajoja. Ensimmäisessä vaiheessa se estää luokan kielletyn paketin lataamisen. Kolmannessa vaiheessa se ei salli epäluotettavan luokan sijoittua luotettuun pakettiin.

Johtopäätös

Luokkakuormainarkkitehtuuri tukee JVM: n tietoturvamallia kahdella tavalla:

  1. erottamalla koodi useisiin nimitiloihin ja asettamalla "kilpi" koodin väliin eri nimiavaruuksiin
  2. vartioimalla luotettujen luokkakirjastojen, kuten Java-sovellusliittymän, rajat

Ohjelmoijien on käytettävä molempia näitä Java-luokan latausarkkitehtuurin ominaisuuksia oikein tarjoamiensa turvallisuusetujen saamiseksi. Nimitila-kilven hyödyntämiseksi eri lähteistä peräisin oleva koodi tulisi ladata eri luokan latausobjektien kautta. Luotettavan pakettirajavalvonnan hyödyntämiseksi luokkakuormaajat on kirjoitettava, jotta he tarkistavat pyydettyjen luokkien nimet rajoitettujen ja kiellettyjen pakettien luettelon perusteella.

Katso Chuck McManis's -oppaasta, miten luokan kuormaaja ja esimerkkikoodi kirjoitetaan JavaWorld artikkeli "Java-luokan latauslaitteiden perusteet".

Ensikuussa

Seuraavan kuukauden artikkelissa jatkan JVM: n suojausmallin keskustelua kuvaamalla luokan todentajaa.

Bill Venners on kirjoittanut ohjelmistoja ammattimaisesti 12 vuotta. Piilaaksossa toimiva hän tarjoaa ohjelmistokonsultointi- ja koulutuspalveluja nimellä Artima Software Company. Vuosien varrella hän on kehittänyt ohjelmistoja kulutuselektroniikka-, koulutus-, puolijohde- ja henkivakuutusteollisuudelle. Hän on ohjelmoinut monilla kielillä monilla alustoilla: kokoonpanokieli useille mikroprosessoreille, C Unixille, C ++ Windowsille, Java Webissä. Hän on kirjoittanut kirjan: Inside the Java Virtual Machine, julkaisija McGraw-Hill.

Lisätietoja tästä aiheesta

  • Kirja Java-virtuaalikoneen määrittely (//www.aw.com/cp/lindholm-yellin.html), kirjoittaneet Tim Lindholm ja Frank Yellin (ISBN 0-201-63452-X), osa Java-sarjaa (//www.aw.com/cp /javaseries.html), Addison-Wesley, on lopullinen Java-virtuaalikoneen viite.
  • Suojattu tietojenkäsittely JavaNow'lla ja tulevaisuudella (valkopaperi) // www.javasoft.com/marketing/collateral/security.html
  • Applet Security UKK

    //www.javasoft.com/sfaq/

  • Matalan tason Java-suojaus, kirjoittanut Frank Yellin //www.javasoft.com/sfaq/verifier.html
  • Java-suojauksen kotisivu

    //www.javasoft.com/security/

  • Katso vihamielisten sovelmien kotisivu

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

  • Kirja Java SecurityHostile-sovelmat, reiät ja vastalääkkeet, Dr. Gary McGraw ja Ed Felton, analysoi perusteellisesti Java-tietoturvakysymykset. //www.rstcorp.com/java-security.html
  • Edelliset "Hupun alla" -artikkelit:
  • Lean, Mean Virtual Machine - Johdanto Java-virtuaalikoneeseen.
  • Java Class File Lifestyle - antaa yleiskuvan Java-luokan tiedostosta, tiedostomuodosta, johon kaikki Java-ohjelmat kootaan.
  • Java's Garbage- Collected Heap - Antaa yleiskuvan roskien keräyksestä yleensä ja erityisesti Java-virtuaalikoneen roskikorista.
  • Bytecode Basics - Esittelee Java-virtuaalikoneen tavukoodit ja käsittelee erityisesti primitiivisiä tyyppejä, muunnosoperaatioita ja pinooperaatioita.
  • Liukulukuaritmeettinen - kuvaa Java-virtuaalikoneen liukulukutukea ja tavukoodeja, jotka suorittavat liukulukutoimintoja.
  • Logiikka ja aritmeettisuus - kuvaa Java-virtuaalikoneen tuen loogiselle ja kokonaislukutaidolle sekä niihin liittyvät tavukoodit.
  • Objektit ja taulukot - Kuvailee, kuinka Java-virtuaalikone käsittelee objekteja ja taulukoita, ja keskustelee asiaankuuluvista tavakoodeista.
  • Poikkeukset - kuvaa, kuinka Java-virtuaalikone käsittelee poikkeuksia, ja keskustelee asiaankuuluvista tavukoodeista.
  • Kokeile lopulta - Kuvailee, kuinka Java-virtuaalikone toteuttaa kokeilulausekkeet, ja keskustelee asiaankuuluvista tavakoodeista.
  • Ohjausvirta - kuvaa, kuinka Java-virtuaalikone toteuttaa ohjausvirtauksen, ja keskustelee asiaankuuluvista tavukoodeista.
  • Agletsin arkkitehtuuri - kuvaa IBM: n autonomisen Java-pohjaisen ohjelmistoagenttitekniikan agletien sisäisen toiminnan.
  • Point of Aglets - analysoi mobiiliagenttien todellisen hyödyllisyyden, kuten agletit, IBM: n autonomisen Java-pohjaisen ohjelmistoagenttitekniikan.
  • Menetelmän kutsuminen ja palautus - kuvaa neljä tapaa, joilla Java-virtuaalikone käyttää menetelmiä, mukaan lukien asiaankuuluvat tavukoodit.
  • Säikeiden synkronointi - näyttää, miten säikeiden synkronointi toimii Java-virtuaalikoneessa. Keskustellaan monitorien sisääntulon ja poistumisen tavukoodeista.
  • Java's Security Architecture - Antaa yleiskuvan JVM: n sisäänrakennetusta suojausmallista ja tarkastelee JVM: n sisäänrakennettuja turvallisuusominaisuuksia.

Tämän tarinan "Turvallisuus ja luokan latausarkkitehtuuri" julkaisi alun perin JavaWorld.