Kirjautuminen

Haku

Tehtävät

Keskustelu: Projektit: SafeEval: PHP-koodin turvatarkistus

Sivun loppuun

Metabolix [21.08.2011 21:45:30]

#

Ohjelmointiputkassa julkaistiin jo aikaa sitten PHP-koodeja suorittava sivu. Sivu lähettää koodit suoritettavaksi ulkoiselle palvelimelle tarkasti rajoitettuun ympäristöön.

Seuraavaksi tavoitteena on tunnistaa joukosta turvalliset koodit ja suorittaa ne paikallisesti. Sitä varten suoritussivulla on koekäytössä koodi, joka pyrkii hyvin pikaisella silmäyksellä erottamaan varmasti turvalliset koodit mahdollisesti vaarallisista. Käytännössä tarkistus etenee näin:

PHP:n syntaksi on kuitenkin monin paikoin niin kiero, että tarkistuksessa voi olla vielä suuriakin aukkoja. Vilkaiskaa ihmeessä koodia (näkyy tuolla suoritussivulla) ja kertokaa, mikä on pielessä tai voiko jollain helpolla konstilla tunnistaa vielä joitain turvallisia koodeja.

Innokkaimmille hakkereille muistutan vielä, että vaikka tarkistus on käytössä, koodin paikallinen suoritus ei ole käytössä. :) Toki myös vanhassa chroot-ympäristössä olevista puutteista saa ilmoittaa.

Jaska [21.08.2011 22:23:17]

#

En tunne PHP:n turvallisuuspuolta kovinkaan hyvin, joten kiinnostaisi tietää, tunnistaako koodi jos merkit koodataan Unicodena, jolloin esimerkiksi U+003C;U+003C;U+003C vastaa merkkijonoa <<<, tai jos merkit koodataan ASCII:na.

Käsittääkseni varsin yksinkertaiselta näyttävät kielet voivat olla Turing-täydellisiä, eli jäljelle jää aika yksinkertainen PHP:n osajoukko, jolla työskennellään. Vai mitenkä varmistetaan, että kukaan ei koodaa eval()-funktion vastinetta joillain muilla funktioilla ja ehtolausekkeilla?

The Alchemist [21.08.2011 22:59:27]

#

Ja mitäs tällä nyt sitten olisi tarkoitus tehdä, kun edes muuttujia ei voi käyttää ollenkaan?

Antti Laaksonen [21.08.2011 23:37:13]

#

Muuttujien käyttämistä ei ole estetty, vaan tarkistaja poistaa koodissa olevat muuttujat ennen kiellettyjen sanojen tarkistamista. Esimerkiksi jos koodissa on muuttuja $eval, tämä ei haittaa, vaikka eval on kielletty sana. Siksi tarkistaja poistaa muuttujan $eval koodista ennen kuin se etsii siitä sanaa eval.

Jaska kirjoitti:

Käsittääkseni varsin yksinkertaiselta näyttävät kielet voivat olla Turing-täydellisiä, eli jäljelle jää aika yksinkertainen PHP:n osajoukko, jolla työskennellään. Vai mitenkä varmistetaan, että kukaan ei koodaa eval()-funktion vastinetta joillain muilla funktioilla ja ehtolausekkeilla?

Turing-täydellinen osajoukko PHP:stä voi olla turvallinen. Esimerkiksi voimme tehdä tarkistajan, joka hyväksyy vain sellaiset PHP-koodit, joissa on ennalta määrätty Turing-konetta simuloiva koodi sekä merkkijono, joka kuvaa halutun Turing-koneen tilasiirtymät ja nauhan alkusisällön. Tällaisen PHP-koodin voi varmasti suorittaa turvallisesti, ja silti kyseessä on Turing-täydellinen osajoukko PHP:stä. Olennaista on sen sijaan kieltää vaaralliset PHP:n funktiot kuten tiedostoja käsittelevät funktiot.

jlaire [22.08.2011 03:09:17]

#

Jaska kirjoitti:

En tunne PHP:n turvallisuuspuolta kovinkaan hyvin, joten kiinnostaisi tietää, tunnistaako koodi jos merkit koodataan Unicodena, jolloin esimerkiksi U+003C;U+003C;U+003C vastaa merkkijonoa <<<, tai jos merkit koodataan ASCII:na.

PHP:n lähdekoodissa ei tietääkseni voi käyttää tuollaisia merkintöjä. Merkkijonoihin voit kyllä tallentaa ihan mitä haluat, mutta siitä ei ole paljoa hyötyä kun se eval() on kielletty.

Metabolix [22.08.2011 15:15:27]

#

The Alchemist kirjoitti:

Ja mitäs tällä nyt sitten olisi tarkoitus tehdä, kun edes muuttujia ei voi käyttää ollenkaan?

Selostin alussa tarkistusalgoritmin etenemisen, en mitään pysyvää koodin muokkausta. Tarkistuksessa poistetaan turvalliset osat ja hylätään vaaralliset, ja jos mitään vaarallista ei löydy, koodi suoritetaan aivan alkuperäisessä muodossaan. (Turhien osien poisto helpottaa olennaisten kohtien tarkistusta.)

Jaska kirjoitti:

En tunne PHP:n turvallisuuspuolta kovinkaan hyvin, joten kiinnostaisi tietää, tunnistaako koodi jos merkit koodataan Unicodena, jolloin esimerkiksi U+003C;U+003C;U+003C vastaa merkkijonoa <<<, tai jos merkit koodataan ASCII:na.

PHP on (ainakin tällä hetkellä) merkistöltään 8-bittinen. Koodin kannalta olennaiset merkit ovat aina ASCII-muodossa.

Jaska kirjoitti:

Vai mitenkä varmistetaan, että kukaan ei koodaa eval()-funktion vastinetta joillain muilla funktioilla ja ehtolausekkeilla?

Koodi ajetaan PHP-tulkin sisällä. Ainoa tapa tehdä asioita on siis ajaa oikea PHP-koodi; muutahan tulkki ei suorita. Tarkistin tutkii yhden PHP-koodin ja varmistaa, että se ei ole itsessään vaarallinen ja että se ei aja muuta PHP-koodia. Jälkimmäisestä seuraa, että tarkistin tarkistaa itse asiassa kaiken suoritettavan PHP-koodin.

Vaikka joku kirjoittaisi PHP:llä C-kääntäjän ja tuottaisi sillä haitallisen ohjelman, tätä ohjelmaa ei voisi mitenkään suorittaa tai edes tallentaa levylle. PHP:llä tulkattava kieli taas on rajoittunut siihen, mitä tulkki osaa tehdä, ja nyt tulkki ei voi osata vaarallisia asioita, koska ne on tarkistuksessa estetty.

Turingin koneella ei ole tässä asiassa juuri osaa eikä arpaa. Eihän sillä viime kädessä voi kuin muuttaa yhden lukujonon toiseksi – olkoonkin, että tähän muutokseen liittyy matemaattisesti hienoja mahdollisuuksia.

jcd3nton [22.08.2011 16:41:36]

#

Koodin tarkistajasta en sano mitaan, mutta chrootin ja tulkin ajamiseen liittyvat perusohjeet toki kannattaa kerrata (vaikka tod. nak. tiedat jo kaiken tarpeellisen).

Eli oikeudet tiedostoihin minimoidaan. Jos tulkin ei koskaan tarvitse kirjoittaa mitaan, chrootin voi laittaa omalle osiolleen, joka mountataan read-onlyna. /devin alla yleensa on laitteita, joiden pelkka lukemien voi kutkuttaa liiaksi bugista kernelikoodia. Siksi kannattaa jattaa vain ehdottomat laitteet sinne. Linuxilla myos esim. /proc voi olla tarpeeton. Chroottauksen jalkeen mikaan prosessi ei saa pyoria roottina, ja setuid & setgid -binaarit tulisi ottaa pois. Tarpeettomat syscallit kannattanee kieltaa kokonaan, jolloin tarkistusseulan ohi pujahtanut kutsu ei mene lapi. Myos tarpeellisten syscallien parametreja voi rajoittaa. Threadit, forkkaukset, ja muut vastaavat kannattaa kieltaa kokonaan, jos ei niita oikeasti tarvita; nain valtytaan erikoisilta race-tilanteilta.

Metabolix [23.08.2011 05:43:39]

#

Täydensin sallittujen funktioiden listaa, ja riemukseni huomasin, että PHP sisältää valmiin parserin (token_get_all). Kirjoitin koko tarkistuksen nyt uudestaan tämän funktion avulla. Koodista tuli paljon yksinkertaisempi (joskin siinä on pitkiä listoja), ja kunnollisen parserin ansiosta myös aiemmin vaarallisilta vaikuttaneet rakenteet (<<<, {$koodi} ja ${koodi}) voidaan hyväksyä.

Testausapua toivon edelleen.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta