-
Translated by Jouko Voutilainen (ITKST56 course assignment at JYU.fi)
-
Teksti: PHP7:n epäsarjallistamisen hyödyntäminen
"Vanhojen temppujen opettaminen uudelle koiralle"
-
Noniin hyvää huomenta.
-
Hyvää huomenta ja tervetuloa taas päivämme toiseen esitelmään.
-
Puhujamme on turvallisuustutkija CheckPointilla
-
ja hän esitelmöi meille PHP7 sarjallistamismekanismien hyödyntämisestä.
-
Antakaa siis suuret aplodit Yannay Livneh:lle.
-
(Yleisö taputtaa
-
Hei ja tervetuloa esitelmääni:
-
"Opettamassa uudelle koiralle vanhoja temppuja."
-
Kyse on PHP7 sisäisestä muistista turvallisuustutkijoille.
-
Tiedoksi alkuun, että kyseessä ei ole puhe PHP-koodista
-
vaan PHP7-tulkista.
-
Toivottavasti nautitte.
-
Alkuun hieman itsestäni.
-
Nimeni on Yannay ja työskentelen CheckPointissa.
-
Tiimini ja minä työskentelemme monien asioiden parissa:
-
Verkko, sulautetut laitteet, käyttäjäpuolen haavoittuvuusasiat.
-
Lisäksi myös muistin korruptoimisen.
-
Tämän päivän agenda:
-
Ensiksi lyhyt alustus PHP:stä ja sen jälkeen
-
PHP:n unserializesta.
-
Sitten ZVAL järjestelmä: PHP7:n arvojärjestelmä.
-
Tämän tiedon pohjalta hieman bugeja ja haavoittuvuuksia.
-
Sitten PHP7:n jakajasta. Ja näiden
-
hyödyntämistä edellisen tiedon pohjalta
-
näemme miten voimme exploitata näitä bugeja sekä suorittaa koodia etänä
-
Sitten johtopäätökset ja keskustelu jne.
-
Aloitetaanpa. PHP on kaikkein käytetyin web-sovellusten kieli.
-
Kyseessä on palvelinpuolen kieli ja palvelimet hallitsevat maailmaa.
-
Kaikki tietomme web-sovelluksissa on palvelimilla.
-
On hyvin mielenkiintoista miten hyökkääjä saa tietonsa useiten serveriltä.
-
Kun sanoin sen olevan käytetyin tämän päivän kieli,
-
tänään käytetyimmän kielen versio on v5.
-
Mutta juuri julkaistu versio on v7
-
ja tästä me puhumme tänään.
-
Se on siis yksi tärkeimmistä kielistä tänä päivänä,
-
mutta miten sen ja PHP-sovellusten turvallisuus?
-
Jokaisessa suositussa kielessä on haavoittuvuuksia
-
tai sillä on kirjoitettu niitä.
-
Tiedämme miten paljon SQLi ja XSS-haavoittuvuuksia on ilmennyt viime vuosina.
-
Nämä ovat korkean tason haavoittuvuuksia
-
ja ne riippuvat sovellukseen kirjoitetusta koodista.
-
Mutta on olemassa myös muistikorruptiota.
-
Miten muistikorruptiota voi olla korkealla tasolla saatat kysyä?
-
Osa PHP:n toiminnallisuudesta on käsitelty tulkissa,
-
joka on kirjoitettu C-kielellä.
-
Ja kun syötät käyttäjätietoja tällaiseen toiminnallisuuteen
-
ja siellä on bugeja, saatat törmätä muistikorruptioon.
-
Paras esimerkki tästä on UNSEARLIZE("epäsarjallistamisen")-funktio,
-
jota on hyväksikäytetty monissa tilanteissa viime vuosien aikana.
-
Ja tämä on juurikin se funktio josta tänään puhumme,
-
mutta PHP7:n liittyen.
-
Mitäpä unserializen historiasta?
-
Liikaa CVE:itä laskettavaksi.
-
Ja suurin osa näistä CVE:istä on olioinjektiosta.
-
Ominaisuusorientoitunut ohjelmointi,
-
jos olet kuullut siitä.
-
Tähän on looginen hyväksikäyttötapa.
-
Se liittyy sovellukseen kirjoitustapaan.
-
Mutta siihen liittyy myös muistikorruptiota.
-
Muistikorruptio ei liity itse sovellukseen.
-
Muistikorruption hyväksykäyttäminen perustuu ainoastaan PHP-versioon.
-
Niinkuin mainitsin. Versio 5 tai 7.
-
Muistikorruptioista PHP5:ssä:
-
Siinä oli geneerinen exploitti.
-
Ionicin Stefan Essarin tekemä.
-
Siitä kirjoitettiin Blackhat:ssa 2010.
-
Ja tämä exploit käytännössä toimi missä tahansa PHP5:n unserialize-muistikorruptiossa.
-
Eli niinkuin mainitsin se on vanha ongelma.
-
Tässä on esimerkki tältä vuodelta heinäkuulta.
-
Tämä pieni nettisivu, en tiedä oletko tietoinen siitä,
-
avasi Bug-Bounty:n ja tämä herätti huomion Evenide-yritykseltä.
-
He tarkastelivat API:a ja huomasivat tämän API POST-pyyntö.
-
Tässä voitte nähdä evästeen,
-
jolla on mielenkiintoinen formaatti.
-
Tämä on unseralizen formaatti.
-
Ja kun lähetät pyynnön ja saat vastauksen ja näet,
-
että tämä eväste käsitellään.
-
Eli meillä on haavoittuvainen sarjallistaminen juurikin tässä.
-
Ja he fuzzasivat unserialize-funktiota versio 5:ssä
-
löytäen uuden haavoittuvuuden, hyödyntäen sitä ja saaden palkkion.
-
Eli mitenkä PHP7:ssä.
-
Se on uusi kielen julkaisu,
-
julkaistu noin vuosi sitten.
-
He järjestelivät kaiken tehokkuusnäkökulmalla.
-
He uusivat value-systeemin.
-
Uudelleenimplementoivat muistiallokaatiomekanismi.
-
Ja tästä syystä muistikorruption exploit-tekniikat eivät toimi enää.
-
Muistikorruption hyödyntäminen riippuu vahvasti muistin järjestystavasta.
-
Kun kaiken tämän muuttaa,
-
mikään ei enää toimi.
-
Mutta meillä on vieläkin unserialize-toiminnallisuus PHP7:ssä,
-
sillä jonkin verran taaksepäin yhteensopivuutta löytyy.
-
On ollut joitakin CVE:itä.
-
Olioinjektio edelleen toimii,
-
sillä se on puhtaasti loogista.
-
Mutta muistikorruptiot, vaikka ne edelleenkin voi löytää unserializessa,
-
etä-exploitteja ei ollut vasta kuin tämän esitelmän jälkeen.
-
Enemmän tai vähemmän.
-
Kyllä, kiitoksia vain minulle.
-
Eli puhutaanpa unserializesta:
-
Ensiksi minun pitää selventää jotakin.
-
Sinun pitäisi sanoa "deserialize".
-
Unserialize on kieliopillisesti väärin ja jos se häiritsee sinua,
-
niin sitten niin käy koko tämän esitelmän ajan.
-
Eli olen pahoillani.
-
Mutta koska PHP on PHP voimme edetä.
-
Tämä on sarjallistamisen dokumentointi PHP:ssä.
-
Käytännössä sarjallistaminen ottaa arvon,
-
ja muuttaa sen merkkijonoksi,
-
jonka voi säilöä ja palauttaa myöhemmin.
-
Unserialize on tämän vastakohta.
-
Eli saat merkkijonon sarjallistamisen tietyssä formaatissa,
-
ja muutat sen takaisin arvoksi.
-
Ja tämä on hyvin yksinkertaista,
-
voisit sanoa,
-
mutta tässä on ollu liian paljon haavoittuvuuksia ja näemme juurikin miksi.
-
Eli katsotaanpa esimerkki sarjallistamisesta.
-
Eli kohta haluamme sarjallistaa tämän kivan taulukon,
-
jonka sisällä on toinen taulukko ja niin edelleen.
-
Etenemme askel askeleelta,
-
ja sarjallistamme sen unserialisoituun formaattiin.
-
Ensiksi sarjallistamme taulukon neljällä elementillä.
-
Eli kuten näette alla,
-
meillä on merkkijono ja se on a-kaksoispiste-4.
-
A tarkoittaa saraketta, 4 neljälle arvolle.
-
Ja PHP:ssä jokainen taulukkon on itseasiassa hash-taulukko tai sanakirja,
-
eli se on avain-arvo-varasto.
-
Mutta kun sinulla on taulukko,
-
avaimet ovat epäsuoria.
-
Avaimet ovat vain juokseva indeksointi ja se on sokeaa.
-
Eli sarjallistamme ensimmäisen arvon avaimenaan kokonaisluku 0.
-
Eli sinulla on i-kaksoispiste-nolla.
-
ja seuraavaksi arvon pariin.
-
Seuraavaksi sarjallistamme kokonaisluvun 1 avaimeksi ja kokonaisluvun 1337 arvoksi.
-
Sitten sarjallistamme merkkijonon.
-
Eli meillä on kokonaisluku 2 avaimena ja lukujono.
-
Eli meillä on s lukujonona, kaksoispiste, sarake 5,
-
viideksi merkiksi ja sitten meillä on "apple",
-
joka on merkkijonon arvo.
-
Nyt sarjallistamme taas uuden taulukon.
-
Eli meillä on epäsuora avain kokonaisluku 3
-
ja arvo a-kaksoispiste-kolme, kolmea arvoa varten tässä sisäkkäisessä taulukossa.
-
Seuraavaksi meillä on epäsuora avain merkkijono a,
-
eli meillä on s merkkijonona,
-
kaksoispiste-1 yhtä arvoa varten,
-
a merkkijonon arvoksi ja tämä on se avain.
-
Ja arvo on kokonaisluku 1.
-
Seuraavaksi sarjallistamme luokan ja olion.
-
Oikeastaan, eli meillä on...
-
Palaamme takaisin epäsuoriin avaimiin,
-
eli kokonaisluku 0 epäsuorana lukuna.
-
Sitten meillä on olio, jonka luokkanimessä on 8 merkkiä.
-
Eli se on kaksoispiste-8-kaksoispiste-luokan nimi "stdClass".
-
Sitten meillä on sarakkeet 0. 0 on ominaisuuksien määrä tässä oliossa.
-
0 ominaisuutta=Ei mitään luokassa.
-
Kaarisulkeiden välissä tyhjää.
-
Ja sitten sarjallistamme kokonaisluvun 1 avaimena ja kokonaisluvun 7331 arvona.
-
Ja tämä oli sarjallistamisen prosessi.
-
Sangen yksinkertaista ja meillä on tämä mukava formaatti,
-
josta nyt tiedämme.
-
Seuraavaksi haluan näyttää teille unserializen.
-
Ja tämä tulee olemaan täysin päinvastainen prosessi,
-
eli se tulee olemaan hieman tylsä,
-
mutta haluan näyttää teille tässä jotakin.
-
PHP tukee viittaukset(references)-nimistä toimintoa.
-
Viittaukset tarkoittavat että unserializen aikana,
-
voimme määrittää formaatissa kokonaisluvun
-
tai merkkijonon asemasta viittauksen.
-
Ja tämä kertoo PHP-mekanismille palata takaisin ja tarkastaa,
-
mikä oli äskeinen jäsennetty arvo,
-
ja haluan kopion siitä arvosta tai viittaukset siihen arvoon.
-
Jotta tämä toiminto on mahdollinen unserializen aikana,
-
jokaisesta unserialize-mekanismin käsittelevästä arvosta,
-
on pidetty viittaus. Joten meillä on taulukko nimeltä var_hash -taulukko.
-
Ja tässä taulukossa meillä on osoittimet jokaiseen käsiteltyyn arvoon.
-
Katsotaanpa miten se toteutetaan.
-
Ensiksi unserialisoidaan taulukko, jossa on 4 elementtiä.
-
Eli näette var_hash -taulukossa, joka on 1-pohjainen taulukko,
-
meillä on osoitin tähän taulukkoon, jonka juuri loimme.
-
Seuraavaksi meillä on avain: kokonaisluku 0 ja arvo NULL.
-
Ja voimme nähdä että toinen osoitin osoittaa juuri käsittelemäämme NULL-arvoon.
-
Seuraavaksi meillä on kokonaisluku 1,
-
jonka arvona on 1337. Ja kolmas osoitin osoittaa 1337:ään.
-
Sitten meillä on merkkijono "apple" arvona,
-
ja neljäs osoitin osoittaa tähän arvoon.
-
Seuraavaksi meillä on sisäinen taulukko,
-
mutta var_hash taulukko on flat-taulukko.
-
Vaikka meillä on hieman sisäkkäisiä taulukoita tässä,
-
arvot ovat sisäkkäisiä ja var_hash taulukko on litteä (flat).
-
Viides osoitin osoittaa taulukkoon.
-
Seuraavaksi unserialisoimme avaimen a ja arvon 1
-
ja meillä on uusi osoitin tähän arvoon.
-
Sitten luomme std-olion.
-
Eli meillä on toinen olio siellä
-
ja seitsemäs osoitin osoittaa tähän luotuun olioon.
-
Ja nyt jotain mielenkiintoista tulee tapahtumaan.
-
Me unserialisoimme viittauksen kolmanteen arvoon.
-
Eli mitä tulisi tapahtumaan tässä.
-
PHP:n unserialize-toiminnallisuus käy tarkistamassa var_hash -taulukon
-
menemällä kolmanteen arvoon.
-
Kolmas arvo tässä on osoitin kokonaislukuun 1337.
-
Ja nyt meidän täytyy luoda viittaus tähän arvoon,
-
joten tässä on mitä teemme:
-
Me unserialisoimme tämän arvon
-
ja luomme viittauksen aiemmin käsiteltyyn arvoon.
-
Eli näin PHP tukee taaksepäin tapahtuvaa viittaus-toiminnallisuutta.
-
Ja tämä mekanismi, toiminnallisuus,
-
aiheutti paljon bugeja menneisyydessä,
-
sillä kuten näette,
-
me pidämme osoittimia asioihin,
-
joita ehkä tarvitsemme tai emme tarvitse uudestaan.
-
Tässä on ollut hieman hämmennystä kuluneina vuosina.
-
Jos menit sekaisin seuratessa tätä monimutkaista formaattia,
-
minulla on muutama asiat,
-
mitä haluan teidän muistavan.
-
Eli ensiksi se on monimutkainen formaatti.
-
Okei?
-
(Yleisö nauraa)
-
Kyllä on ilmeistäkin,
-
että monimutkainen formaatti johtaa bugeihin,
-
jonka näemme hetken päästä.
-
Meillä on paljon keinoja kontrolloida muistin varausta.
-
Me luomme olioita,
-
unserialisoimme eri mittaisia merkkijonoja ja hash-taulukoita,
-
joten meillä on paljon kontrollia käyttäjinä.
-
Me pidämme nämä viittaukset aiemmin unserialisoituihin asioihin,
-
ja voimme uudelleenkäyttää niitä.
-
Eli tässä tilanteessa voimme käyttää asioita
-
niiden vapauttamisen jälkeen.
-
Onnistuimme vapauttamaan muistista jonkun objektin
-
jollakin taikuudella
-
ja meillä on kuitenkin edelleen osoitin
-
siihen ja näin voimme edetä exploittaajina.
-
Eli nyt puhumme Zvals-systeemistä PHP:ssa.
-
Zvalit ovat käytännössä arvoja.
-
Tämä on miten PHP-tulkki kutsuu arvoja tai säilyttää muuttujia.
-
Tämä on PHP-muuttuja.
-
Olen pahoillani,
-
että meillä PHP:ta tässä,
-
mutta sitä ei ole jatkossa paljoa.
-
Korkean tason kielenä,
-
meillä on muutama toiminnallisuus muuttujillemme.
-
Meillä on automaattinen muistinhallinta tai roskankerääjä.
-
Ja meillä on nämä viittaukset.
-
Viittaukset kun Y:llä viitataan X:ään,
-
se tarkoittaa, että muuttujan Y arvo
-
muuttuu kun arvon X arvo muuttuu,
-
sekä toisinpäin.
-
Eli ne molemmat ovat käytännössä muuttujia,
-
jotka sisältävät saman arvon.
-
Ja tämä on miten zvalit oli implementoitu PHP5:een.
-
Meillä oli tämä tietue,
-
nimeltään zval_struct.
-
Se toimi kekomuistissa,
-
ja viittauslaskettu ja jokainen zval
-
oli käytännössä osoitin tähän tietueeseen
-
ja aina kun loimme uuden zvalin,
-
jouduimme allokoimaan tämän rakenteen ja alustamaan sen.
-
Muistinhallinta oli hyvin ilmiselvä.
-
Meillä oli viittauslaskenta ja
-
muistin syklin tunnistaminen,
-
eli se oli hyvin yksinkertainen algoritmi,
-
jonka suurin osa tietääkin.
-
Tehdäkseen viittauksia,
-
tehdäkseen kaksi muuttujaa osoittamaan
-
samaan arvoon oli kyse vain kahdesta
-
osoittimesta osoittamassa samaan tietueeseen keossa.
-
Kaikki oli hyvin yksinkertaista ja mukavaa.
-
Mutta se oli hidasta.
-
Eli kun implementoitiin PHP7:ää,
-
oli jonkin verran motivaatiota muuttaa sitä.
-
Implementoijat halusivat vähemmän viittauksien poistoa.
-
Aina kun zval oli osoittimena,
-
tarvittiin viittausta muodostaessa osoittimen viittauksen poisto,
-
joka voi olla kallista ja aina kun luodaan uusi arvo,
-
vaikka se olisikin vain lyhyeksi aikaa ja tiedän tarkasti missä se on,
-
joudut kuitenkin tekemään varauksen kekomuistiin,
-
joka voi olla kallista.
-
Eli tämä systeemi suunniteltiin upottamista(embed) varten.
-
Sanottiin:
-
Okei, en halua zvalien olevan vain kekomuistissa vaan haluan,
-
että ne voidaan upottaa
-
mihin tahansa pinossa muissakin tietueissa
-
ja niin edelleen.
-
Ja tämä on miten uusi zval-järjestelmä on implementoitu.
-
Meillä on tämä zval-tietue, mutta nyt se on hieman yksinkertaisempi.
-
Zvalit ovat vain tämä tietue ja tämä tietue sisältää vain arvon ja tyypin.
-
Joten tässä ei ole mitään viittausten laskentaa.
-
Ja me voimme laittaa tämän tietueen mihin vain haluamme.
-
Arvo voi olla tässä jokin kahdesta:
-
Se voi olla primitiivinen tyyppi,
-
esimerkiksi primitiivinen C-tyyppi,
-
kuten kokonaisluku tai liukuluku ja niin edelleen.
-
Mutta PHP tukee myös merkkijonoja.
-
Eli jos haluamme tukea monimutkaisia tyyppejä
-
kuten merkkijonoja tai objekteja,
-
tämä arvo olisi osoitin johonkin monimutkaiseen tietueeseen.
-
Tämä tietue olisi kekomuistissa.
-
Eli tämä tietue ei olisi pinossa vaan jossakin kekomuistissa.
-
Ja se olisi myös viittauslaskettu.
-
Eli tässä on esimerkki.
-
Tämä on kokonaisluku ja muistissa meillä on vain arvo 1337.
-
Ja tyyppi long.
-
Siinä se, emme tiedä missä se on,
-
ja se on hyvin yksinkertainen.
-
Nyt tukeaksemme viittaustenlaskentaa sen vastuu on sillä,
-
kuka tahansa alustaa sen zvalin.
-
Jos zval on tietueessa, kuka ikinä sen alustaakin sen,
-
joutuu myös tyhjentää sen.
-
Mutta tässä on yksi ongelmakohta.
-
Jos arvo on primitiivinen, kaikki on hyvin.
-
Mutta jos kyseessä on osoitin toiseen tietueeseen,
-
tämä tietue tulisi olla viittauslaskettu.
-
Ja näin roskankerääjä toimii.
-
Se tarkistaa zvalin osoittaman arvon
-
ja sillä on myös viittauslaskenta ja roskankerääjä.
-
Ja nyt katsotaanpa esimerkki.
-
Okei eli tässä on merkkijonotietue,
-
kuten sanoin se on monimutkainen tyyppi,
-
joten tämä tietue on kekomuistissa ja se on osoitettu zvalilla.
-
Kuten näette,
-
ensimmäinen kenttä tässä tietueessa on viittauslaskenta.
-
Ja viimeinen kenttä on joustava taulukko.
-
Joten, kun allokoitaessa merkkijonoa,
-
me allokoimme riittävästi dataa, muistia, säilöäksemme merkkijonon
-
sisällön ja pääsemme siihen käsiski tämän kentän kautta.
-
Tältä se näyttää taulukossa,
-
kun alustamme merkkijonomuuttujan.
-
Sitten meillä on zval-tietue tyyppiä merkkijono.
-
Allokoimme tämän merkkijonon kekoon.
-
Alustamme sen näillä arvoilla.
-
Näette arvon "apple" tässä.
-
Ja me vain osoitamme tämän zvalin tähän merkkijonoon
-
ja viittauslaskentaluku on 1.
-
Ja tämä tietue on keossa.
-
Eli miten me voimme hallita viittauksia.
-
Miten viittaustoiminnallisuus implementoitiin.
-
Tällä kertaa emme voi tehdä vain yhtä zval-osoitinta toiseen,
-
sillä ne saattavat olla eri tasoilla.
-
Toinen voi olla tietueessa ja toinen pinossa ja niiden tulee olla hallittu, eikö?
-
Eli tähän on ratkaisu.
-
PHP:ssä implementoitiin uusi tyyppi nimeltä references (viittaukset).
-
Tämä on helpompi näyttää kuin selittää,
-
joten näytän miten se toimii.
-
Oletetaan että teillä on muuttuja X luvulla 1337 ja sitten meillä on muuttuja Y,
-
jolla on viittaus muuttujaan X.
-
Eli meillä on se nyt muistissa ja haluamme tehdä viittauksen siihen.
-
Eli me alustamme uuden tietueen kekoon nimeltä reference.
-
Ja tällä tietueella on kaksi kenttää.
-
Ensimmäinen kenttä on viittauslaskenta ja toinen on zval.
-
Ja me alustamme tämän zval-arvon olemaan sama kuin X.
-
Joten näette, että sillä on kopio X:n arvosta.
-
Sen jälkeen vaihdamme X:n tyypin viittaukseksi,
-
jonka jälkeen se viittaa _zend_referenceen.
-
Ja nyt voimme alustaa Y:n ja se tulee olemaan sama.
-
Eli se on myös viittaus johonkin kekomuistissa.
-
Eli siirsimme X:n sisällön kekoon ja nyt meillä voi olla kaksi zval-muuttujaa X ja Y.
-
Ne vaan osoittavat kekomuistiin niinkuin aiemminkin.
-
Pääasia muistaa zvaleista on,
-
että ne on suunniteltu upotteiksi,
-
eli ne voivat olla monissakin paikoissa,
-
jotka voivat johtaa bugeihin.
-
Tavoitteet saavutettiin kun oli vähemmän viittauksenpoistoja
-
ja vähemmän keon käyttöä.
-
Mutta viittausten tekeminen on hieman monimutkaista.
-
Viittaus ei ole toiminnallisuus jota käytetään paljon muualla kuin exploiteissa.
-
Eli tässä on kompromissi:
-
Zvalit eivät ole kaikkein yksinkertaisin juttu,
-
mutta viittaukset ovat monimutkaisempia
-
ja se on tämän kompromissin arvoista minun mielestäni ainakin.
-
Eli nyt kun tiedämme unserializesta ja zvalista,
-
katsotaanpa hieman bugeja ja haavoittuvuuksia.
-
Eli ensiksi määrittämättömien arvojen käyttäminen.
-
Sillä zvalit olivat alunperin osoittimia.
-
Osoittimien alustaminen oli helppoa.
-
Kaikki tietävät miten osoitin alustetaan.
-
Osoitit vain nulliin ja se oli siinä.
-
Tietueiden alustaminen on hieman eri tarina.
-
Ne joudutaan alustamaan jonkin macrojen tai vakiomuuttjien kanssa.
-
Se saattaa vaatia hieman aikaa ja ohjelmoijilla on tapana ohittaa tämä vaihe.
-
Jos se on mahdollista, et alusta tietueita,
-
mikä on ongelma.
-
Tämä voi johtaa joihinkin haavoittuvuuksiin.
-
Ja tässä on juurikin se esimerkkinä.
-
Meillä on tämä SplObjectStorage::unserialize-funktio.
-
Tämä funktio on mukautettu implementaatio SpLObjectStoragen unserializesta.
-
Tämä luokka on implementoitu C-koodissa.
-
Osa luokista SPL:ssä, joka on yksi PHP:n kirjastoista,
-
ovat implementoitu C:ssä, ja siitä on tässä kyse.
-
Kuten näette ensimmäisellä rivillä.
-
Kaksi arvoa on määritetty: entry ja inf.
-
Nämä ovat zval-arvoja.
-
Eli ovat zval-tietue-typpiä.
-
Ja niitä ei missään vaiheessa alusteta tässä koodissa.
-
Ja muutaman rivin jälkeen pääsemme tähän lauseeseen,
-
jossa kutsutaan php_var_unserialize-funktiota.
-
Tämä on C-implementaatio unserialize-funktiosta.
-
Ensimmäinen arvo on viittaus tähän inf-arvoon,
-
jota ei koskaan alustettu.
-
Tämän tuli olla out-muuttuja, mutta se ei ole. Okei.
-
Mutta tässä aiomme säilöä merkkijonon ja unserialisoida sen.
-
Seuraava muuttuja on p.
-
P osoittaa merkkijonoon jota ollaan unserialisoimassa.
-
Joten mitä tämä funktio tekee.
-
Se unserialisoi P:n osoittaman merkkijonon ja säilöö arvon inf-muuttujaan.
-
Kuitenkin sisäisesti päädymme tähän riville:
-
"zval pointer destroy",
-
joka tarkoittaa
-
"olkaa hyvä ja tuhotkaa tämä zval",
-
johon viitataan rval-muuttujalla.
-
Ja mikä on rval meidän tilanteessamme?
-
Se on inf. Se on juurikin se asia,
-
mitä emme alustaneet.
-
Ja syy miksi koodi tekee tämän,
-
on varmistaakseen ettei zvalissa ole mitään arvoa ennen kuin siihen ollaan kirjoittamassa uusia arvoja.
-
Mutta koska tätä arvoa ei koskaan alustettu,
-
tämä arvo on pelkkää roskaa stackista.
-
Ja jos muodostat pinosi oikein,
-
voit aiheuttaa pahoja asioita.
-
Joten tämä oli CVE-2016-7480.
-
Seuraava esimerkki on tyyppihämmennys/-sekaannus.
-
Me aiomme luottaa siihen faktaan,
-
että viittausten tekeminen on hyvin monimutkainen prosessi kuten näitte.
-
Ja se muuttaa zvalin tyyppiä.
-
Ja me voimme olettaa,
-
että joku unohti tämän mahdollisuuden
-
ja tämä on juurikin se mitä tapahtui.
-
Joten meillä on sama funktio uusiksi.
-
Tässä on hieman enemmän koodia samasta funktiosta,
-
mutta se on siis SplObjectStoragen unserialize.
-
Ja kuten näette toisella rivillä,
-
kutsumme sisäistä unserializea
-
ja muunnamme taas p:n osoittaman merkkijonon
-
ja tallennamme tuloksen zval entryyn. Okei?
-
Kaksi riviä myöhemmin tarkastamme
-
juuri äsken unserialisoimamme asian tyypin.
-
Tarkastaaksemme, että se on olio-tyyppiä.
-
Jos entryn tyyppi ei ole object,
-
funktio epäonnistuu:
-
Huonoja asioita tapahtuu.
-
Mutta jos se on tyyppiä object, voimme jatkaa.
-
Ja viimeisellä rivillä unserialisoimme seuraavan arvon.
-
P on edennyt ja nyt se osoittaa eteenpäin merkkijonossa
-
ja me muutamme p:n osoittaman merkkijonon
-
ja tallennamme sen inf-muuttujaan.
-
Mutta mitä tapahtuu, jos inf on oikeasti viittaus entryyn.
-
No, entryn tyyppi muuttuu. Ja katsotaanpa mitä tapahtuu.
-
Eli ensiksi unserialisoimme entryn ja se on olio.
-
Me tarkastamme, että tämä on oikeasti olio ja kaikki on hyvin.
-
Mutta seuraavaksi me unserialisoimme inf:n.
-
Ja inf on viittaus entryyn.
-
Joten prosessin mukaan,
-
ensiksi allokoimme _zend_reference:n kekoon,
-
ja alustamme sen olemaan entryn kopio.
-
Sitten vaihdamme entryn tyypin viittaukseksi
-
ja osoitamme sen tähän viittaukseen.
-
Ja tietysti lopuksi alustamme inf:n.
-
Mutta tässä prosessissa,
-
me oikeastaan vaihdamme entryn tyypin sen jälkeen,
-
kun se on tarkistettu.
-
Tämä on siis bugi ja huonoja asioita tapahtuu.
-
Se ei ole exploitti, mutta se on bugi ja se korjattiin.
-
Tämä on siis BUG #73258 PHP-system():ssä.
-
Tämä on päivän viimeinen bugi.
-
Ja se on "Vapautuksen jälkeinen käyttö".
-
Ongelman juurisyy on se,
-
että zval:t ovat upotettuna tietueisiin.
-
Ja me pidämme osoittimia zvaleihin,
-
mutta tietueilla on omat sääntönsä niiden muokkautumiselle.
-
Jotkut tietueet vaihtavat paikkaa muistissa,
-
kertomatta siitä mitään muuta.
-
Ja jos jatkamme näiden osoittimien käyttöä,
-
me todellisuudessa osoitamme muistipaikkaan,
-
joka ei ole enää pätevä.
-
Eli tällainen dynaaminen tietue voi olla esimeriksi hash-taulukko.
-
Ja tämä koodi process_nested_data -funktiosta.
-
Tämä funktio prosessoi jokaisen hash-taulukon unserializen aikana.
-
Hash-taulukot voivat olla myös olion ominaisuuksia.
-
Tässä ensimmäisellä rivillä määritetään muuttujat
-
ja seuraavalla rivillä lisäämme uuden arvon hash-taulukkoon.
-
Eli mitä teemme tässä zend_hash_add_new,
-
lisäämme uuden arvon.
-
Ensimmäinen parametri on hash-taulukko ja toinen on avain.
-
Funktion tuloksena on osoitin zval-arvoon.
-
Saamme dataa, joka osoittaa zval:iin.
-
Sitten kutsumme viimeistä riviä,
-
joka kutsuu unserialize-funktion sisäistä implementaatiota.
-
Ja se taas muuttaa p:n osoittaman merkkijonon
-
ja säilöön sen arvon muuttujaan data tai mihin data osoittaa.
-
Mutta katsokaapa viimeistä parametriä tässä.
-
Se on var_hash, eli se taulukko,
-
josta puhuimme edellisessä osiossa.
-
var_hash ylläpitää osoittimia jokaiseen arvoon,
-
jonka olemme käsitelleet, mukaanlukien data.
-
Data siis osoittaa sisäisesti hash-taulukkoon
-
ja se säilötään var_hash-taulukkoon.
-
Mutta mitä tapahtuu, jos onnistut lisäämään
-
jonkun muun arvon hash-taulukkoon.
-
Hash-taulukko saattaa muokata kokoaan.
-
Eikö? Hash-taulukot kasvavat joskus muistissa.
-
Kun ne kasvavat,
-
ne sisäisesti uudelleenallokoivat muistiaan sisältääkseen lisää arvoja.
-
Eli tältä se näyttää muistissa.
-
Ensiksi olet unserialisoimassa objektia.
-
Ja tällä objektilla on jotain ominaisuuksia.
-
Esimerkiksi sillä on kaksi ominaisuutta: 0 ja 1.
-
ja sitten onnistumme taianomaisesti lisäämään
-
uuden arvon ominaisuuden hash-taulukkoon.
-
Jolloin tämä uudelleenallokoi itsensä.
-
Eli nyt var_hash osoittaa uudet arvot,
-
jotka unserialisoitiin,
-
mutta kaksi edellistä arvoa eivät ole enää päteviä.
-
Tämä ei ole hyvin yleinen skenaario.
-
Se on hyvin vaikea hyväksikäyttää tai oikeastaan laukaista tätä haavoittuvuutta,
-
koska jos muistat tämän formaatin,
-
ennen olion unserialisoimista sen ominaisuuksien määrä määritetään.
-
Ja PHP varmistaa,
-
että hash-taulukossa on tarpeeksi tilaa
-
säilyttääkseen kaikki nämä ominaisuudet.
-
Mutta... On kaksi tapaa laukaista tämä haavoittuvuus.
-
Ensimmäinen on wakeup-funktio.
-
Tämä on funktio, jonka objektit voivat määrittää.
-
Tätä funktiota, metodia, kutsutaan objektin unserialisoimisen jälkeen.
-
Ja jos jostain syystä tämä funktio määrittää uuden ominaisuuden lennossa,
-
tulkki ei ole tietoinen tästä etukäteen.
-
Eli asettaessa uuden ominaisuuden lennossa,
-
voi laukaista tämän haavoittuvuuden.
-
Ja meillä on lisäksi myös minun lempiobjektini PHP:ssa tai siis luokka,
-
"date interval class".
-
Ja tällä luokalla on hyvin mielenkiintoinen käyttäytyminen.
-
Se ei alusta omia ominaisuuksien hash-taulukkoa etukäteen.
-
Tai se oikeastaan ainoastaan käsiteltäessä tämän objektin ominaisuuksia,
-
se määrittää ja lisää ominaisuutensa hash-taulukkoon.
-
Eli jos onnistumme päätymään johonkin toiminnallisuuteen,
-
esimerkiksi toString tai wakeup,
-
joka käsittelee tämän tai jonkun muun objektin ominaisuuksia,
-
kuten "date interval",
-
voimme laukaista tämän haavoittuvuuden.
-
Ja tämä oli CVE-2016-7479.
-
Eli nämä bugit ovat monimutkaisia.
-
On edelleen olemassa unserialize-haavoittuvuuksia.
-
Jopa tämän esitelmän lähettämisen ja tämän esityksen pitämisen välillä,
-
on raportoitu ja julkistettu ainakin yksi uusi.
-
Haavoittuvuudet ovat hieman erilaisia kuin mitä olemme tottuneet näkemään,
-
sillä zval-systeemi on hieman erilainen,
-
mutta silti muistikorruptiot...
-
Ja nämä haavoittuvuudet antavat meidän käyttää vapautettuja arvoja,
-
kuten olemme nähneet.
-
2 haavoittuvuutta antoivat meidän käyttää
-
vapautettuja arvoja ja tämä on ominaisuus,
-
jota tarvitsemme hyväksikäyttääksemme näitä haavoittuvuuksia.
-
Eli kun nyt tiedämme,
-
miten tämä järjestelmä toimii sisäisesti
-
ja miten zval toimii sekä olemme löytäneet hieman bugeja,
-
aiomme puhua hieman allokaattorista.
-
Sillä exploitatessamme tämänkaltaista muistikorruptiohaavoittuvuutta,
-
meidän pitää tietää,
-
miten allokaattori toimii ja miltä muisti näyttää.
-
Eli meillä oli edellinen PHP5-allokaattori,
-
joka ei ole niin tärkeä,
-
mutta se oli keko-pohjainen allokaattori.
-
Jokainen paikka muistissa sovitti allokaatioyksikön PHP:ssä.
-
Okei, eli sitä kutsutaan paikaksi (slot),
-
ja sillä on koko sekä liput jokaista allokaatiota kohti.
-
Ja myös vapaiden paikkojen lista välimuistia varten.
-
Ja se oli tosi hauska ja kiva hyväksikäyttöä varten,
-
mutta nyt meillä on erilainen allokaattori.
-
Tämä allokaattori tässä on kokonaan uudelleenkirjoitettu.
-
Siinä ei ole mitään samaa,
-
ja se sisältää muistisäiliö kuten te tunnette ne sekä vapaalistan.
-
Tämä on käytännössä miten allokaattori toimii.
-
Nämä ovat käytännössä perus rakennuspalikat.
-
Ja nyt aion heittää teille hieman yksityiskohtia
-
ja te varmaankin näette ne, tai ette.
-
Allokaattori toimii 2 MB paloissa käyttöjärjestelmältä
-
ja nämä palat on jaettu sivuihin.
-
Ensimmäinen sivu on sivukuvaaja,
-
joka kuvaa palan.
-
Sillä on pari tietuetta ja kaksi tärkeää ovat se joka kuvailee sivut:
-
Mitkä sivut ovat käytössä tai
-
vapaana ja se joka sisältää osoittimet muistisäiliö
-
ja vapaisiin muistipaikkoihin,
-
jotka oli alustettu.
-
Ja jokainen muistivarasto on tietyn kokoinen vapaalista.
-
Meillä on 32-tavuiset ja 16-tavuiset.
-
Ja se voi olla useita sivuja pitkä.
-
Nyt katsotaanpa siinä muodossa missä voitte edes muistaa tämän.
-
Eli tässä on yksi 2MB pala käyttöjärjestelmästä. Ja se on jaettu sivuihin.
-
Ensimmäinen sivu on palankuvaaja.
-
Näette vapaat paikat, jotka ovat vain taulukko osoittimia vapaalistoihin.
-
Ja sivuinformaatio jokaista sivua varten.
-
Ja tältä muistisäiliö näyttää.
-
Eli se voi olla useita sivuja pitkä.
-
Tämä on 16-tavuinen säiliö,
-
ja me alustamme sen vapaalistana.
-
Eli jokainen 16 tavua osoittaa seuraaviin tavuihin.
-
Ja me rekisteröimme sen palan kuvauksessa.
-
Joten meillä on sivun tiedot 16 tavua joka on 2 sivun alueella,
-
ja osoittaa vapaalistaan.
-
Allokointialgoritmi on varsin yksinkertainen.
-
Ensiksi olettaen, että haluamme allokoida 30-kokoisen paikan,
-
tarkastamme mihin säiliöön se kuuluu.
-
Uskoisin, että se kuuluu säiliöön numero 5.
-
Sitten tarkistamme onko vapaalistaa vapaana tai onko säiliö alustettu.
-
Jos yhtään alustettua säiliötä ei ole me alustamme uuden säiliön
-
ja otamme sen käyttöön vapaalistasta.
-
Oletetaan, että haluamme allokoida 30 tavua.
-
Nyt ei ole 30-tavuista säiliötä vapaana,
-
joten alustamme uuden säiliön ja otamme sen vapaalistalta.
-
Olettaen, että haluamme tehdä siirron samankokoiseen,
-
se on vieläkin yksinkertaisempaa:
-
Otamme sen vain vapaalistalta.
-
"Free memory" on päinvastainen operaatio.
-
Eli saamme jonkun osoittimen,
-
jonka haluamme vapauttaa takaisin muistivarastoon.
-
Eli tarkistamme mihin palaan se kuuluu
-
ja mille sivulle siinä palassa.
-
Luemme palan kuvauksen,
-
tietääksemme mihin vapaalistaan työntää se takaisin
-
ja työnnämme sen takaisin vapaalistaan.
-
Eli olettaen, että haluamme vapauttaa tämän säiliön ensimmäisen paikan.
-
Silloin katsomme, että se kuuluu kolmanteen sivuun
-
ja kolmas sivu on säiliöstä 32.
-
Menemme vapaalistaan ja puskemme sen takaisin.
-
Haluan muistaa allokaattorista sen,
-
että allokaattori on hyvin ennustettava,
-
mikä on tärkeää meille, eli exploittaajille.
-
Ja on mahdotonta vapauttaa sekalaisia osoittimia.
-
Tätä käytettiin edellisessä exploittitekniikassa,
-
mutta se ei ole enää mahdollista,
-
sillä meillä on bittioperaatioita ja lookup-toimintoja
-
ja on vaikeaa väärentää muistia näyttämään oikeannäköiseltä,
-
jotta tämä toimisi.
-
Ja me voimme hyväksikäyttää vapaalistan osoittimia saadaksemme mielivaltaisia oikeuksia.
-
Eli jos pystymme muuttaamaan vapaalistaa ja allokoimaan,
-
muutamia paikkoja, saatamme pystyä allokoimaan mihin paikkaan vain haluamme.
-
Ja aion selittää sen paljon myöhemmin.
-
Eli nyt kun meillä on haavoittuvuuksia
-
ja tiedämme allokaattorin toiminnasta,
-
on aika kirjoittaa exploitti.
-
Ja jokainen exploitti sisältää pari vaihetta.
-
Kaikkein yleisin on vuodot.
-
Haluamme vuodattaa hieman muisti-informaatiota kiertääksemme ASLR:n.
-
Sitten haluamme lukea hieman muisteja lukemalla dataa tai gadgetteja,
-
funktio-osoittimia jne.
-
Jos haluat kirjoittaa, voit kirjoittaa shell-koodia,
-
ehkä kirjoitat jotain muuta juttua ja me haluaisimme suorittaa koodia.
-
Sitä varten me täällä olemme.
-
Ensimmäinen asia mistä haluan puhua on vuoto.
-
Mielestäni se on kaikkein monimutkaisin vaihe
-
ja aiomme hyväksikäyttää allokaattoria.
-
Se on meidän paras ystävämme tässä.
-
Se perustuu karkeasti edelliseen exploittiin,
-
mutta on sen yleistys.
-
Aiomme käyttää kykyämme sarjallistaa vapautettuja objekteja,
-
ja uskoisin, että pystymme sarjallistamaan objekteja.
-
Ei pelkästään käyttämään niitä,
-
sillä tällä tavalla alunperin aloitimmekin.
-
Meillä oli unserialize. Jos unserialisoimme jotain,
-
se todennäköisesti oli aiemmin sarjallistettu.
-
Meillä on jonkinlainen mekanismi,
-
jolla sarjallistamme jotain ja unserialisoimme ja sarjallistamme takaisin
-
ja niin edespäin.
-
Allokaattori, jos muistatte, on vapaalista.
-
Eli se ohittaa kaiken, joka sille syötetään.
-
Eli jos vapautamme osoittimia allokaattori ohittaa ne.
-
Ja kun olemme vapauttaneet ja käyttäneet niitä,
-
voimme lukea näiden osoittimien kautta ja lukea jotain dataa,
-
joka oli myös vapautettu.
-
Eli tällä tavalla se tulee toimimaan.
-
Allokaattori on vapaalista ja ensimmäinen osoitin näissä vapaissa paikoissa on seuraava paikka.
-
Sehän on vain se osoitin, eikö?
-
Tässä on vapaan paikan tietue,
-
ja kuten näette, ensimmäinen kenttä on osoitin.
-
Kun luemme vapautettuja objekteja,
-
pystymme joskus lukemaan tämän osoittimen kautta.
-
Tarkoitan, että me vapautimme paikan ja edelleen käytämme sitä,
-
eli voimme lukea tämän osoittimen kautta seuraavaa vapaata paikkaa.
-
Eli tässä on minun lempiluokkani PHP:ssä:
-
Date interval -luokka.
-
Ja kuten näette, tässä on miten tietue on implementoitu muistissa
-
ja ensimmäinen kenttä on osoitin.
-
Kuinka onnekkaita olemmekaan. EIkös?
-
Se osoittaa tähän tietueeseen.
-
Tämä tietue on hyvin yksinkertainen.
-
Sillä on paljon kenttiä, mutta ne kaikki ovat kokonaislukuja.
-
Ne eivät pelkästään ole kokonaislukuja,
-
vaan "unsigned long long",
-
eli ne myös unserialisoidaan ja luetaan takaisin käyttäjälle.
-
Kun tätä luokkaa unserialisoidaan,
-
saamme myös nämä numerot: vuosi, kuukausi, päivä jne.
-
Eli miten väärennämme vuodot käytännössä.
-
Ensiksi allokoimme tämän DateIntervalin
-
ja allokoimme jonkun objektin vuodettavaksi,
-
esimerkiksi merkkijonon.
-
Sitten vapautamme molemmat objektit,
-
ensiksi merkkijonon ja seuraavaksi DateIntervalin.
-
Eli allokaattori aikoo ohittaa DateIntervalin osoittimella vapautettuun merkkijonoon,
-
koska näin se toimii.
-
Allokaattori ohittaa myös tämän merkkijonon joillakin osoittimilla.
-
Eli kun sarjallistamme tämän DateIntervalin,
-
aiomme lukea tämän objektin
-
Ja tässä on teille hieman hex-dumppia,
-
sillä todellakin halusitte sitä.
-
Ja tässä näette vapaalistan ennen kuin aloitamme exploittimme,
-
ja nyt allokoimme DateIntervalin.
-
Kuten näette, se osoittaa johonkin tietueeseen,
-
jonka alustin arvolla -1-luvuilla, koska sillä ei ole juurikaan merkitystä.
-
Allokoimme, tai siis unserialisoimme merkkijonon yksi toisensa jälkeen.
-
Ja nyt vapautamme nämä kaksi ja kuten näette DateInterval osoitin,
-
ensimmäinen osoitin, osoittaa vapautettuun merkkijonoon.
-
Ja sarjallistaessa tätä DateIntervalia,
-
se oikeastaan saa arvonsa merkkijonosta.
-
Se saa nämä osoittimet kokonaislukuina,
-
joka on varsin mukavaa.
-
Kuinka voimme lukea muistia?
-
Meillä on tämä hyvin kiva tietue jo valmiiksi olemassa.
-
Jos pystymme kontrolloimaan zvalia täydellisesti,
-
voimme vain vaihtaa tämän osoittimen mihin tahansa vain haluamme.
-
Eli ensimmäiseen kenttään osoittaminen DateIntervalissa
-
antaa meidän lukea minkälaista muistia tahansa.
-
Jos emme kontrolloi zvalia täysin,
-
mikä voi ollakin.
-
64-bittisessä se oli näin.
-
On olemassa monimutkaisempikin tapa,
-
mutta en aio puhua siitä tässä.
-
Mutta käytännössä voimme käyttää erilaista oliota:
-
DatePeriod-oliota, jonka ensimmäinen kenttä on osoitin,
-
joka osoittaa toiseen tietueeseen ja tämä tietue hallitsee toista osoitinta,
-
joka on annettu eteenpäin strcpy:lle unserialisoinnin yhteydessä.
-
Eli voimme lukea muistia strcpy:llä.
-
Ja voitte nähdä kaikki yksityiskohdat
-
julkaisemassani artikkelissa aiemmin tänä vuonna.
-
Annan teille linkit tämän esitelmän lopussa.
-
Miten voimme kirjoittaa muistiin?
-
Muistiin kirjoittaminen on paljon monimutkaisempaa.
-
Tässä on mitä aiomme tehdä.
-
Aiomme vapauttaa merkkijonoja takaisin allokaattorille.
-
Ja merkkijonoihin aiomme kirjoittaa osoittimia,
-
mihin tahansa muistiin haluammekin kirjoittaa.
-
Sitten aiomme hyväksikäyttää vapaalistaa.
-
Aiomme vaihtaa osoittimia vapaalistassa
-
ja aion lisätä tai vähentää niitä,
-
riippuen haavoittuvuudestamme eteenpäin muistissa.
-
Ja jossain vaiheessa lisätessämme niitä tarpeeksi,
-
ne oikeastaan osoittavat siihen muistikohtaan mihin haluamme kirjoittaa.
-
Eli muutaman allokoinnen jälkeen,
-
muistiallokaattori antaa meille osoitteen johon haluamme kirjoittaa.
-
Tältä näyttää mitä haluamme tehdä.
-
Eli miten voimme vapauttaa nämä merkkijonot?
-
Kuten sanoin,
-
jokainen käsittelemämme unserialisoitu arvo saa viittauksen var_hash-taulukkoon.
-
Eli meillä on viittaus lähes kaikkeen
-
ja mitään ei vapauteta unserialisoinnin yhteydessä.
-
On kuitenkin olemassa yksi poikkeus.
-
Hash-taulukossa voimme käyttää samaa avainta kahdesti.
-
Avaimiin ei säilytetä viittauksia.
-
Ja jos käytämme samaa avainta kahdesti,
-
ja avaimet voivat olla merkkijonoja.
-
Toisella kertaa käytettäessä avainta,
-
se vapautuu. Hash-taulukko katsoo avainta ja toteaa:
-
"Minulla on jo tuo avain, en tarvitse sitä uudestaan",
-
ja vapauttaa sen takaisin allokaattorille.
-
Mitään viittauksia siihen ei ole tehtynä
-
ja se on takaisin allokaattorissa meitä varten.
-
Seuraavaksi meidän pitää tietää miten hyväksikäyttää osoittimia vapaalistassa.
-
Tämä on kaikkein mielenkiintoisin osa tässä.
-
Syy miksi se on mahdollista,
-
ja se on hyvin yleistä,
-
on sillä meillä on tässä tyyppihämmennystä.
-
Meillä on vapaat paikat, jonka ensimmäinen kenttä on osoitin.
-
Mutta meillä on myös jotain vapautettuna.
-
Arvo, joka vapautettii, johon meillä on edelleen viittaus.
-
Ja kekomuistissa kaikilla tietueilla on viittauslaskenta.
-
Viittauslaskenta on aina ensimmäinen kenttä.
-
Eli jos otetaan esimerkiksi _zend_object.
-
Tämän tietueen ensimmäinen kenttä on viittauslaskenta.
-
Eli jos meillä on tyyppihämmennystä olion ja...
-
Tai ei tyyppihämmennys,
-
mutta jos objekti olisi vapautettu ja voisimme edelleen käyttää sitä,
-
kasvattamalla tai vähentämällä viittauksia tähän olioon,
-
oikeastaan kasvattaa tai vähentää osoitinta.
-
Eli tällä tavalla voimme kontrolloida tätä osoitinta.
-
Tässä vähän lisää hex-dumppia.
-
Eli tämä on osa exploittia,
-
jonka kirjoitin bugiin 71311.
-
Ja tässä näette, että vapautimme merkkijonot jo takaisin allokaattorille.
-
Eli näette neljäykköset hex-dumpissa.
-
Ja nyt aiomme laukaista haavoittuvuuden.
-
Tämä haavoittuvuus on taulukko-objekti-luokassa.
-
Tämän jäsentäminen kasvattaa osoittimen arvoa vapaalistassa kahdella.
-
Ja nyt meillä on vapautuksen jälkeinen käyttö tässä osoitteessa,
-
johon vapaalista osoittaa.
-
Se on edelleen allokaattorissa,
-
mutta meillä on viittaus siihen.
-
Ja se oli 11. arvo, jonka jäsensimme,
-
eli viittauksen lisääminen tähän osoitteseen.
-
Eli R11 jäsentää R11 jne.
-
Me kasvatamme tätä osoitinta kahdella joka kerta.
-
Ja jossain vaiheessa päädymme arvoon,
-
joka juuri vapautettiin allokaattorille.
-
Eli nyt jos allokoimme kahdesti tästä säiliöstä,
-
ensimmäisellä kerralla allokoimme äskettäisen korruptoituneen objektin
-
ja toisella kertaa voimme kirjoittaa 414141:een,
-
ja saamme segmentointivirheen.
-
Tämä on juurikin se mitä halusimmekin.
-
Eli koodin suorittaminen.
-
Kaiken tämän jälkeen koodin suorittaminen on sangen yksinkertaista.
-
Jos kontrolloimme zvalia,
-
yksinkertaisin tapa, kuten sanoin,
-
on ohittaa takaisinkutsu.
-
Kun hallitset jotain objektia,
-
voit päättää mitä takaisinkutsuja sillä on.
-
Mutta jos et kontrolloi zvalia täysin,
-
voit vain... Meillä on oikea primitiivi.
-
Eli voimme kirjoittaa funktion osoittimen ja se on aikalailla siinä.
-
Eli: opittavaa tästä exploitista.
-
Allokaattori on ystäväsi,
-
käytä sitä viisaasti.
-
Nämä primitiiviset tietotyypit ovat uudelleenkäytettäviä,
-
niitä voi käyttää monissa eri haavoittuvuuksissa liittyen unserialisointi-mekanismeihin.
-
Yhdistäen nämä kaikki primitiivit,
-
pystyt suorittamaan koodia etänä (RCE)
-
Johtopäätöksiä: Vaikka kirjoitat koodia korkean tason kielellä kuten PHP,
-
olet edelleen haavoittuvainen muistikorruptioon
-
tai muihin matalan tason ongelmiin.
-
PHP:n uusi malli perustuu tehokkuuteen.
-
Sinulla on edelleen haavoittuvuuksia.
-
En usko, että se on sen turvallisempi tai turvattomampi.
-
Allokaattori on exploitti-ystävällinen.
-
Kun kirjoitat exploittia, käytä sitä.
-
Ja älä ikinä ikinä käytä unserialisea.
-
Tämä funktio on käytännössä on etänä koodin suorittamista varten.
-
Jokainen kerta, kun se on ollut koodissa tavoitettavissa,
-
sitä on hyväksikäytetty.
-
Lisää tietoa löydät checkpoint-blogista,
-
ja myös tämän esitelmän kuvaustekstissä on linkki julkaisemaani artikkeliin.
-
Lähiaikoina toinenkin julkaisu tulee tulemaan puhumistani haavoittuvuuksista.
-
Lisää tietoa ja myös kolmas haavoittuvuus,
-
josta en tässä puhunut.
-
PHP bugisysteemi on toinen linkki
-
ja siellä on kaikki listatut bugit sekä haavoittuvuudet.
-
Osalla bugeista ei ole CVE:tä ikävä kyllä.
-
Kolmas linkki on Nikita Popova-blogi.
-
Uskoisin, että äänsin hänen nimensä oikein.
-
Hän on PHP:n pääkontribuuttori
-
ja hänellä on paljon selityksiä PHP:n sisäisistä mekanismeista.
-
Jos haluatte olla minuun yhteydessä,
-
teillä on minun yrityssähköposti, Twitter ja olen yannayl
-
monilla muilla alustoilla,
-
kuten gmail jne. Couch surfing, enpä tiedä.
-
Eli tässäpä tämä. Onko kysyttäviä?
-
(Yleisö taputtaa)
-
Kiitos Yannay.
-
Jos teillä on kysymyksiä,
-
olkaa hyvä ja asettukaa jonoon mikrofonien viereen ja kysykää kysymyksenne.
-
Jos olet lähdössä, tehkää se hiljaa.
-
Onko kysymyksiä täältä tai internetistä?
-
Ihmiset ovat ällikällä lyötyjä.
-
Aloitan sitten itse kysymyksellä,
-
koska minulla on yksi.
-
En ymmärtänyt sisäisiä juttuja ihan hirveästi,
-
mutta tietyissä hyväksikäytön tavoissa,
-
joista puhutaan, voimmeko olettaa näkemämme tätä luonnossa?
-
Oikeastaan PHP7 ei ole hirveän laajalti käytetty tällä hetkellä.
-
Luulisin, että se on noin 2%.
-
Se on vasta vuoden vanha,
-
mutta kunhan suuret alustat ja sisällönhallintajärjestelmät
-
siirtyvät tähän uuteen kieleen ennustan,
-
että tulemme näkemään jotain näistä ja muista haavoittuvuuksista.
-
Mutta uskon, että näemme exploitteja tapahtuvan.
-
Kiitos
-
Kysymyksiä yleisöltä tai internetistä?
-
Internetillä on kysymys.
-
Kyllä.
-
Onko olemassa mitään suosittuja projekteja,
-
joihin nämä haavoittuvuudet vaikuttavat?
-
Ei tietääkseni, sillä PHP7 ei ole vielä laajalti käytössä.
-
Mikään suuri sisällönhallintajärjestelmä ei käytä PHP7:ää.
-
(Naurua yleisöstä)
-
Anteeksi.
-
Internet, jos teillä on muita kysymyksiä, olkaa hyvä.
-
Kukaan yleisöstä? Viimeinen mahdollisuus.
-
Okei,
-
taas antakaa suuret aplodit Yannaylle hyvästä esitelmästä.
-
Kiitos.
-
(Yleisö taputtaa)
-
(Teemamusiikki soi)
-
Translated by Jouko Voutilainen (ITKST56 course assignment at JYU.fi)