HTML

RobbeR tech és magánblogja

kontakt:RobbeR at RobbeR pont hu

Egyéb publikálások: Elte-IK blogja
saját weboldal: RobbeR.hu

Webisztán

Nincs megjeleníthető elem

Címkék

Indafotós képek

Friss topikok

Linkblog

MyVIP.hu biztonsági hiba

2008.11.12. 22:06 RobbeR

Nagyon-nagyon rég volt már techpost, ezért most bemutatok nektek egy régebbi, ám elég sokáig működő dolgot. A leírásért nem vállalok felelősséget, de egyúttal biztosítalak is benneteket, hogy már nem működik a dolog. So:

A MyVIP.hu egy igen régóta működő social network, amit szerintem az olvasóim 90%-ának nem kell bemutatnom, akinek meg be kell, annak sem fogom, mert lusta vagyok és emellett bunkó is. Ez az oldal PHP alapú, én pedig egy picit értek a PHP-hez, de ezt nem azért mondom, mert a két dolog között összefüggés van. So...

Ezen a közösségi oldalon nagyon sokáig (konkrétan a nem túl régen bekövetkezett redesignolásig és rendszerkarbantartásig) volt egy nagyon komoly hiba, ami lehetővé tette egy mezei juzernek, hogy Javascript kódot juttasson a saját adatlapjára, ami minden kliens gépén lefut, aki megnézi az adatlapot. A hozzáértőbb olvasó már tudja, hogy igen gáz, ha felhasználótól származó JS kód fut le egy másik felhasználó autentikált kliensén, de a kevésbé hozzáértők kedvéért elmondom, hogy a JS egy olyan eszköz a programozó (vagy esetünkben hacker) kezében, amivel közvetett módon az egész weboldalt tudja befolyásolni (pl DOM-on keresztül), ráadásul kényes információkat is tud vele szerezni a látogató sütijéből.

Itt teszek egy kis kitérőt PHP irányban. A nyelv szerver oldali programok futtatására alkalmas, aminek kimenete kerül kiküldésre a kliens felé a HTTP protokollt felhasználva, de erről már írtam régebben. A szokásos nyelvi elemeken kívül még elég sokmindent támogat, például a munkamenetek kezelését, másnéven a SESSION-öket. Ezek arra jók, hogy egy felhasználó autentikáció után (név, jelszó helyes megadása) "benn is maradjon" az oldalon, tehát lapújratöltésnél ne vesszen el a juzer identitása.

Ezt PHP-ék úgy oldották meg, hogy a $_SESSION nevű szuperglobális tömb elemeit a szerveren tárolják egy fájlban, így a kód lefutása után is létezni fog az adat, amiket az adott oldal egy újratöltésénél, vagy az adott domainen más oldalakról is elérhetünk. A tárolás viszont kevés ahhoz, hogy egyértelműen azonosítani tudjuk a klienst, tehát a kliens-szerver kapcsolatát a következőképpen oldották meg: mikor a $_SESSION tömb értéket kap, a webszerveren létrejön egy file, aminek a neve a felhasználó gépén md5-ben tárolódik - egy sütiben. A süti pedig az egyetlen dolog, amit a kliens akkor is képes elérni, ha azt a szerver nem akarja.

Itt -érdekességként- kitérnék arra, hogy mi is az az md5 (Message-Digest algorithm): Egy  egyirányú kódolási algoritmus. Ezt a kevésbé hozzáértőknek leírom konyhanyelven is: a kódolási algoritmus tulajdonképpen egy módszer, ami lefordít egy adathalmazt egy előre meghatározott titkos abc alapján (persze ez csak egy hasonlat, valójában biteket vesz el és/vagy ad hozzá az adathalmaz bitsorozatához, de a pontos algoritmust nem ismerem). Az md5 esetében ezt csak lefordítani tudjuk, visszafordítani nem, mert a fordítás veszteséges (tehát valószínűleg biteket vesz el az adatból) - máshogy fogalmazva, az md5 visszafejthetetlen. Az én nevem md5-be kódolva például így néz ki: 954c173a4f09f5a6093b203fae341a76, de bárki lefordíthatja a saját nevét ennek az oldalnak a segítségével. Az algoritmus érdekessége, hogy akármekkora a kezdeti adat (1 bájtos, vagy akár 10 GB-os), mindig 128 bites a kimenet, tehát akármit fordítunk md5-be, mindig ugyanolyan hosszú lesz. Ennek fényében nyugodt szívvel ide is írom az interneten használatos jelszavamat md5-ben: (utólag törölve - crakced :D), mert a Brute Force módszeren kívül ezt sehogy máshogy nem tudjátok visszafejteni.

Ha valaki mégis pályázik a jelszavamra, és van fölösleges 100-200millió éve (vagy egy szuperszámítógépe, és pár százezer éve, esetleg több szuperszámítógépe és pár tízezer éve) annak leírom -szintén érdekességként (nem tartozik a poszt témájához)- , hogy mégis mi az a Brute Force.

A Brute Force egy olyan módszer, ami az összes lehetséges kombinációt végigpróbálja mindaddig, amég rá nem talál a helyes megoldásra. A módszert nagyrészt jelszótörésekhez használják, de akad olyan eset (például a fent említett md5 crack), amikor egészen másra. Példa: Egy weboldalon 4-12 karakteres lehet egy jelszó, és tegyük fel, hogy csak az angol ábécé kis és nagybetűit tartalmazhatja (a legtöbb weboldalon speciális karaktert és számokat is tartalmazhat, csak a példa miatt egyszerűsítem le). Ekkor a Brute Force módszer elindul az 'aaaa' karakterlánctól, és meg sem áll a 'ZZZZZZZZZZZZ' karakterláncig, feltéve ha nem találta meg közben a keresett jelszót. A módszert akár "kézzel" is alkalmazhatjuk, de egyszerűbb, ha programot írunk rá - merem feltételezni hogy a számítógép gyorsabb bármelyikünknél...

Ez eddig OK, de számoljuk már össze, hogy 'aaaa' és 'ZZZZZZZZZZZZ' között hány lehetséges kombináció van: Ha jól számoltam, akkor az angol ábécében 26 karakter van, ezt szorozzuk meg kettővel, mert lehet kis és nagy karakter is a példánkban. A jelszó, amit keresünk maximum 12, de minimum 4 karakteres lehet, és egy helyen 52 külömböző karakter állhat, vagyis nem egészen. Ha egy jelszó csak 4 karakteres, akkor a jelszó ötödik karaktere üres, és az ez utániak is üresek. Kurva szar vagyok matekból, de ha a jelszó csak 4 karakteres, akkor is 56^4 különböző kombináció van, ami majdnem 10millió. Ha jól gondolom, akkor 5 karakteres jelszó esetén ez a szám már (56^4)+(56^5), ami 570 millió, de ha nem jól gondolom, akkor javítsatok ki kommentben.

A lényeg az, hogy a lehetséges karakterszám növekedésével drámaian megnő a lehetséges kombinációk száma, ami -mint láthattuk- már 4 karakteres, csupa kis és nagybetűs jelszó esetében is ultrakibaszott nagy. És akkor még nem is vettük számításba a számokat, speciális karaktereket, stb.

Amikor én legutóbb próbáltam egy Brutus nevű programmal -Brute Force módszerrel- feltörni a saját elveszett freemailes fiókom jelszavát, akkor a program másodpercenként 30 külömböző jelszót próbált ki, és kiszámolta, hogy több száz millió év kell az összes kipróbálásához. Szóval a módszer előnye, hogy minden esetben működőképes, hátránya, hogy nagyon-nagyon lassú.

A jelszavam visszafejtéséhez csak írnotok kell egy programot, ami az összes lehetséges jelszókombinációt md5-be fordítja, és összehasonlítja a fent leírt hash-el. Ha ugyanaz, akkor a jelszavam az a karakterlánc, amit a program legutóbb md5-be fordított. Annyit elárulok, hogy kis és nagybetűket, valamint számokat is tartalmaz, de speciális karaktert nem. Sok szerencsét!

Visszakanyarodva az eredeti T-mához, ott tartottunk, hogy a SESSION tömb elemeit a webszerver egy fájlban tárolja, aminek nevét a kliens egy sütibe menti. Minden felhasználónak a MyVIP-en (bejelentkezés után) van egy ilyen sütije, amiben benne van a SESSION_ID-je, ami tulajdonképpen egy webszerveren található fájl neve. Értelemszerűen két felhasználó nem kaphatja ugyanazt a file-t, tehát a juzer sütijében található md5 kód egyfajta azonosító - ez alapján tudja azonosítani a szerver, hogy épp melyik klienssel kommunikál. Ezt a kódot amúgy Ti is lekérhetitek a Mozilla Firefox böngészővel, méghozzá a Tools(Eszközök) -> Options(Beállítások) -> Privacy(Személyes) -> Show Cookies(sütik mutatása) gombra kattintva, és a myvip.hu-hoz tartozó értékeket kikeresve, sőt ha kitörlitek, akkor az oldal az egyértelmű azonosító hiányában ki fog léptetni. Az érték neve 'myviphu_sessid', vagy 'myvipcom_sessid' attól függően, hogy melyik tartománynév alatt vagyunk belépve.

A süti az egyetlen dolog, amit szerver és kliens oldalról is egyaránt elérünk, ezen kívül mindent vagy a szerver, vagy a kliens ér el, a kettő együtt nem. Ha a MyVIPen adatlapomba beágyazok egy olyan JavaScript kódot, ami egy rejtett keretet(iframe) generál, elérési útja pedig egy másik, saját szerveren lévő php oldal (pl: http://www.robber.hu/q.php), akkor a másik szerveren lévő oldalnak paraméterként adva a session ID-t el tudom lopni azt.

Leírok egy teljes példát: x és y felhasználók a MyVIP-en, x a hacker, y a gyanútlan felhasználó. Mindkettő rendelkezik egy saját session_id-vel, ami a sütijükbe van tárolva. Ha y megnézi x adatlapját, akkor az oda x által beágyazott javascript kód generál egy rejtett oldalt az oldalon belül, ami meghívja x saját php fájlját(egy távoli szerveren), ami elmenti y sütijének tartalmát. Tehát x birtokában lesz y identitásának kulcsa, már csak annyi a dolga, hogy a saját session_id-jét átírja a frissen szerzett session_id-re, majd frissít egyet, és azonnal y identitásával lesz bejelentkezve. Egy normálisan megírt rendszer ilyenkor érzékeli, hogy egy file-t két felhasználó használ, de a MyVIP nincs normálisan megírva, ennek ellenére a teszteknél ~10%-ban előfordult, hogy y-t kiléptette, x-et pedig bennhagyta a rendszerben.

Ez a módszer csak akkor működik, ha y autentikációja a MyVIP.hu-ra még mindig él, tehát nem lépett ki -nem semmisítette meg a szerveren lévő fájlját- azóta, hogy azt x lementette. y kétféle módon semmisítheti meg az autentikációját: Kilépés gombra kattint (ami meghívja a php session_destroy() függvényét, ami üríti a $_SESSION tömböt), vagy bezárja a böngészőt (aminek hatására az összes élő autentikáció megszűnik). Mivel ezt x tudja, ezért ír egy w.php-t, ami 10 másodpercenként frissíti magát, és ellenőrzi, hogy megtörtént-e már az adatbázisbejegyzés q.php által. Ha igen, azonnal jelez x-nek egy alert ablakkal, aki ebből <=10 másodperces pontossággal tudni fogja, hogy y megnézte az adatlapját.

A módszerben még plusz jó, hogy a MyVIP a juzer email címét is tárolja a sütiben, tehát egy nagyon gonosz hekker egy ismerős-megjelölő, vagy egy adatlap-nézegető bottal végiglépkedve a juzereken, akár milliós nagyságrendű spam-adatbázist is össze tud hozni, ami a spammerek körében kibaszott sokat ér anyagilag. Egyébként kipróbáltam, és a MyVIP nincs levédve semmiféle botprogram ellen - akár 1000 oldalletöltést is véghezvihetek másodpercenként (durván nuke-olva a szervert), a rendszer szarik rá.

Ez volt a technikai része, az ötlet része viszont még hátra van: Amikor a MyVIP-nek kb 1millió felhasználója volt, rájöttem, hogy a nicknevembe is be tudtam szúrni HTML-t vagy JS-t, ami nem is csak az adatlapomon jelenik meg, hanem keresésben, ismerősök között, vagy akár meghívó feladójánál, meg még egy csomó helyen. Ezt viszont mások is felfedezték, és csilivili gombokat, képeket injektáltak a neveikbe, sőt, olyat is láttam, aki a saját adatlapjára mutató iframet tett a nicknevébe, rekurzívan megölve ezzel bármilyen böngészőt. MyVIP-ék ezt nem sokáig hagyták, amilyen gyorsan jött a felfedezés, olyan gyorsan be is foltozták, ráraktak egy strip_tags-et a nicknévre, és az összes személyes adatra.

Az ez utáni dolgok már több napos forráskód böngészés és próbálkozások eredményei voltak, és végül újabb injection forrást találtam: a képalbumok nevei nem voltak levédve. Ezek az adatlapon egy SELECT-ben jelentek meg, tehát egy </option></select> után bármilyen JS kódot betehettem az adatlapomba. Természetesen jófej voltam, és írtam nekik egy emailt a hibáról, és 2-3 hét alatt sikerült is nekik bepötyögni egy fuckin' strip_tags-et az egymilliós nagyságrendű portáljuk kódjába. Később bővítették az oldalt videófeltötlés funkcióval, ahol szintén nem volt levédve az albumok nevei, és természetesen én megint szóltam nekik, ezt viszont már annyira leszarták, hogy ki sem javították.

Az összes ilyen jellegű hiba a legutóbbi redesign és rendszerkarbantartás alkalmával javítva lett, utána már egyáltalán nem találtam olyan pontot az adatlapon, ahová injektálni lehetne (persze ez nem jelenti azt, hogy nincs is). Viszont már elég rég benn van nekik az openWYSIWYG nevű texteditor a levélírás funkciónál, aminek van egy csomó dokumentált és nemdokumentált hibája, szinte kizártnak tartom, hogy egy ilyen komplex javascript cuccban ne lenne hiba, úgyhogy ha legközelebb bugkereséshez támad kedvem, a célpont már megvan.

Ha valaki esetleg találkozott már máshol is hasonló hibával, vagy van valami huncut kis ötlete 'hibakeresés' címszó alatt, akkor kíváncsian várom az emailemre. Például annak a látogatónak is grat, aki az admin felületembe javascriptet tett, a google keresőkifejezések logolását kihasználva.

Ha hibát találtok a leírásban, vagy valótlant írtam, azt is jelezzétek pls.

2 komment

Címkék: tech javascript php kocka myvip.hu

A bejegyzés trackback címe:

https://robber.blog.hu/api/trackback/id/tr68766156

Kommentek:

A hozzászólások a vonatkozó jogszabályok  értelmében felhasználói tartalomnak minősülnek, értük a szolgáltatás technikai  üzemeltetője semmilyen felelősséget nem vállal, azokat nem ellenőrzi. Kifogás esetén forduljon a blog szerkesztőjéhez. Részletek a  Felhasználási feltételekben és az adatvédelmi tájékoztatóban.

qwerty 2008.11.15. 21:49:02

ahha...szóval egyszer régen ezért voltál a látogatóim közt, mert tudtad h megnézem az adatlapod...:D
amugy fasza post lett:D

RobbeR 2008.11.15. 22:14:00

biztos benne voltál a teszt intervallumban:D
süti beállítások módosítása