Ohjelmointi

Turvallisuus ja luokan todentaja

Tämän kuukauden artikkeli jatkaa Java-suojausmallin keskustelua, joka aloitettiin elokuun "Hoodin alla" -kohdassa. Siinä artikkelissa annoin yleiskatsauksen Java-virtuaalikoneeseen (JVM) sisäänrakennetuista suojausmekanismeista. Katsoin myös tarkasti yhtä näiden turvamekanismien näkökohtaa: JVM: n sisäänrakennettuja turvaominaisuuksia. Syyskuun "Under the Hood" -ohjelmassa tarkastelin luokan kuormaajaarkkitehtuuria, joka on toinen osa JVM: n sisäänrakennettuja turvamekanismeja. Tässä kuussa keskityn JVM: n turvallisuusstrategian kolmanteen osaan: luokan todentajaan.

Luokkatiedoston todentaja

Jokaisella Java-virtuaalikoneella on luokkatiedostovahvistin, joka varmistaa, että ladatuilla luokkatiedostoilla on asianmukainen sisäinen rakenne. Jos luokan tiedostotarkistaja löytää ongelman luokkatiedostossa, se aiheuttaa poikkeuksen. Koska luokkatiedosto on vain binääridatan sekvenssi, virtuaalikone ei voi tietää, onko tietyn luokan tiedosto luotu tarkoittavalla Java-kääntäjällä vai varjoisilla kekseillä, jotka ovat taipuneet vaarantamaan virtuaalikoneen eheyden. Tämän seurauksena kaikilla JVM-toteutuksilla on luokkatiedostotodennus, joka voidaan kutsua epäluotettaviin luokkiin varmistaakseen, että luokkia on turvallista käyttää.

Yksi turvallisuustavoitteista, jonka luokan tiedostotarkistaja auttaa saavuttamaan, on ohjelman vankkuus. Jos buginen kääntäjä tai taitava cracker loi luokkatiedoston, joka sisälsi menetelmän, jonka tavukoodit sisälsivät käskyn hypätä menetelmän lopun yli, kyseinen menetelmä voisi, jos sitä käytetään, aiheuttaa virtuaalikoneen kaatumisen. Siksi vankkuuden vuoksi on tärkeää, että virtuaalikone tarkistaa tuotujen tavukoodien eheyden.

Vaikka Java-virtuaalikoneiden suunnittelijat saavat päättää, milloin heidän virtuaalikoneensa suorittavat nämä tarkistukset, monet toteutukset tarkistavat eniten heti luokan lataamisen jälkeen. Tällainen virtuaalikone analysoi tavukoodit (ja tarkistaa niiden eheyden) kerran, ennen kuin ne koskaan suoritetaan. Osana tavukoodien tarkistusta Java-virtuaalikone varmistaa, että kaikki hyppyohjeet - esimerkiksi mene (hyppää aina), jos (hyppy, jos pinon yläosa on nolla) jne. - aiheuta hyppy toiseen kelvolliseen käskyyn menetelmän tavukoodivirrassa. Tämän seurauksena virtuaalikoneen ei tarvitse tarkistaa kelvollista kohdetta joka kerta, kun se kohtaa hyppykäskyn suorittaessaan tavukoodeja. Useimmissa tapauksissa kaikkien tavukoodien tarkistaminen kerran ennen niiden suorittamista on tehokkaampi tapa taata kestävyys kuin tarkistaa jokaisen tavukoodin käskyn joka kerta, kun se suoritetaan.

Luokkatiedoston todentaja, joka suorittaa tarkastuksen mahdollisimman aikaisin, toimii todennäköisesti kahdessa erillisessä vaiheessa. Ensimmäisen vaiheen aikana, joka tapahtuu heti luokan lataamisen jälkeen, luokan tiedostotarkastaja tarkistaa luokkatiedoston sisäisen rakenteen, mukaan lukien sen sisältämien tavukoodien eheyden. Toisen vaiheen aikana, joka tapahtuu tavukoodien suorituksen aikana, luokkatiedostotarkistin vahvistaa symbolisesti viitattujen luokkien, kenttien ja menetelmien olemassaolon.

Ensimmäinen vaihe: Sisäiset tarkastukset

Ensimmäisen vaiheen aikana luokan tiedostotarkistaja tarkistaa kaiken, mikä on mahdollista tarkistaa luokkatiedostossa tarkastelemalla vain itse luokkatiedostoa (tutkimatta muita luokkia tai käyttöliittymiä). Luokkatiedostovahvistimen ensimmäinen vaihe varmistaa, että tuotu luokkatiedosto on asianmukaisesti muotoiltu, sisäisesti johdonmukainen, noudattaa Java-ohjelmointikielen rajoituksia ja sisältää tavukoodeja, jotka Java-virtuaalikoneen on turvallista suorittaa. Jos luokan tiedostotarkistaja toteaa, että mikään näistä ei ole totta, se heittää virheen, eikä ohjelma koskaan käytä luokkatiedostoa.

Tarkistetaan muoto ja sisäinen yhdenmukaisuus

Tavarakoodien eheyden varmistamisen lisäksi todentaja tarkistaa ensimmäisen vaiheen aikana useita luokkatiedostomuodon ja sisäisen johdonmukaisuuden. Esimerkiksi jokaisen luokkatiedoston on aloitettava samoilla neljällä tavulla, maagisella numerolla: 0xCAFEBABE. Maagisten numeroiden tarkoituksena on helpottaa tiedostojen jäsentäjien tietyn tyyppisen tiedoston tunnistamista. Siksi ensimmäinen asia, jonka luokkatiedostojen todentaja todennäköisesti tarkistaa, on se, että tuotu tiedosto todellakin alkaa 0xCAFEBABE.

Luokkatiedostotarkistin tarkistaa myös, ettei luokkatiedostoa ole katkaistu eikä parannettu ylimääräisillä tavuilla. Vaikka eri luokkatiedostot voivat olla eri pituisia, jokainen luokkatiedoston sisällä oleva yksittäinen komponentti ilmoittaa sen pituuden ja tyypin. Todentaja voi komponenttityyppien ja pituuksien avulla määrittää oikean kokonaispituuden kullekin yksittäiselle luokkatiedostolle. Tällä tavoin se voi varmistaa, että tuotun tiedoston pituus on yhdenmukainen sen sisäisen sisällön kanssa.

Todentaja tarkastelee myös yksittäisiä komponentteja varmistaakseen, että ne ovat hyvin muotoiltuja esimerkkejä komponenttityypistään. Esimerkiksi menetelmän kuvaus (menetelmän palautustyyppi sekä sen parametrien lukumäärä ja tyypit) tallennetaan luokkatiedostoon merkkijonona, jonka on noudatettava tiettyä kontekstivapaata kielioppia. Yksi tarkastuksista, jotka todentaja suorittaa yksittäisille komponenteille, on varmistaa, että kukin menetelmän kuvaus on hyvin muodostettu merkkijono asianmukaisesta kieliopista.

Lisäksi luokkatiedostotarkistaja tarkistaa, että luokka itse noudattaa tiettyjä rajoituksia, jotka sille asettavat Java-ohjelmointikielen määritykset. Esimerkiksi todentaja panee täytäntöön säännön, jonka mukaan kaikki luokat paitsi luokka Esine, täytyy olla superluokka. Siksi luokan tiedostotarkistaja tarkistaa ajon aikana joitain Java-kielisääntöjä, jotka olisi pitänyt panna täytäntöön käännösaikana. Koska todentajalla ei ole mitään keinoa tietää, luonutko luokkatiedosto hyväntahtoinen, virheetön kääntäjä, se tarkistaa jokaisen luokkatiedoston varmistaakseen, että sääntöjä noudatetaan.