A weblap feltöréssel foglalkozó sorozatunk jelenlegi részében az elérési út visszaléptetés, azaz a path traversal sebezhetőséggel foglalkozunk. A hiba nagyon gyakori, és meglehetősen nagy rést nyit a támadók számára.
Az elérési út visszaléptetéssel akkor próbálkozhat a támadó ha a webalkalmazásban egy olyan helyet talál ami a szerveren egy létező fájlt próbál meghívni. Tipikusan ilyen helyek a fájl fel és letöltéseket kiszolgáló részek, a képek, dokumentumok, pdf fájlok megjelenítése, letöltésre kínálása és néha a weblap tartalmának megjelenítése is.
A támadási felület
Ha a következők egyikét látjuk, vagy hasonlót sejtünk egy URL-ben (vagy egy POST-ban) akkor ott már biztosan érdemes próbálkozni.
http://sehol.se/getfile.php?file=access.log
http://sehol.se/?inc=fooldal
http://sehol.se/download.php?f=201012.pdf
Ezek a hívások a szerver oldalon általában (PHP-nál) egy include
vagy egy require
metódus hívással lesznek kiszolgálva. A második példánál nincs megadva a meghívott fájl kiterjesztése. Ilyenkor vagy nincs is neki, vagy az alkalmazás hozzáilleszt automatikusan egy fix végződést, pl azt, hogy .php
. A programozó ezzel kívánta korlátozni, hogy milyen típusú fájlokat lehessen elérni. Előfordul az is, hogy a megtekinthető fájlokat egy select
elemből kell kiválasztanunk és ez hivatott arra, hogy más fájlokat ne érhessen el a látogató.
A sebezhetőség tesztelése
Ha találtunk az alkalmazásban valami a fentiekhez hasonló mintát, akkor első próbaként azt kell megnéznünk, hogy elfogad-e az alkalmazás más könyvtárra való hivatkozásokat is. Ennek módja, hogy meghívjuk a http://sehol.se/getfile.php?file=./nincsisilyen/../access.log
URL-t. Ugye a ./
azt jelenti, hogy induljunk ki abból a könyvtárból amiből egyébként is kiindultunk volna, aztán lépjünk bele a nincsisilyen/
mappába és onnan lépjünk egy mappával feljebb ../
. Ezzel ugye visszajutottunk oda ahol voltunk, azaz egy szempontból a ./nincsisilyen/../
részlet olyan mintha ott sem lenne. A megcélzott szerveren a shell általában lesz olyan intelligens, hogy felismerje azt, hogy a belelépek és kilépek nem változtat semmit és ezért nem problémázik azon, hogy egy nem létező nincsisilyen
nevű mappába akarok belépni.
Ha az alkalmazás kiszolgálja ezt a kérésünket akkor lehet, hogy sebezhető egy path traversal típusú támadásra. Ha nem szolgálja ki a kérést és kapunk hibaüzenetet, hogy nincs ilyen file, akkor a hibaüzenetből megláthatjuk, hogy kiszűrte-e a ../
karaktereket vagy sem.
Ha az alkalmazás megszűrte a megadott fájlnevünket, akkor megpróbálhatjuk a /
jelek helyett ugyanazt a hívást \
jelekkel. Kódolhatjuk a hívásainkat is, hátha valamelyikre nincs felkészítve a szűrő.
Karakter | URL kódolt | 16 bites unicode | Dupla url |
. |
%2e | %u002e | %252e |
/ |
%2f | %u2215 | %252f |
\ |
%5c | %u2216 | %255c |
Ezeken felül a fenti kódolások tetszőleges kombinációja is sikert eredményezhet, így a .
karaktert megadhatjuk %c0%2e
, %e0%40%ae
, %c0ae
stb formátumokban.
A sima szűrést megpróbálhatjuk úgy is kikerülni, hogy ../
helyett ....//
-t adunk meg, így ha az alkalmazás egyszerűen csak kiszűri a ../
részt akkor ami marad az pont az mint ami nekünk kell.
Természetesen ha nagyobb számú variációt akarunk végigpróbálgatni, akkor vagy írunk rá egy nyúlfarknyi scriptet, vagy igénybe vesszük pl a Burp-ot.
A path traversal kihasználása
Többnyire a file hívás automatikusan figyelmen kívül hagyja, ha a szerver root mappája fölé akarunk lépni, Így ha a ../../../../../../../../../../etc/passwd
névvel próbálkozunk, ami 10 szintet lép fel, de valójában csak 7-et lehetne, akkor a kérésünk sikeresen lefut és kiszolgálja nekünk a szerver felhasználóinak nevét, titkosított jelszavát, stb.
Ha olyan helyet tesztelünk ami nem fájlt olvas, hanem ír, akkor vizsgáljuk meg azt, hogy a rendszer más üzenetet ad-e a ../../../../../../../../../../tmp/
és a ../../../../../../../../../../tmp/test.txt
megadásakor. Az első esetben ugye egy könyvtárat akarunk írni, ezt nem fogja engedni, a másik esetben pedig egy fájlt. Ha tudjuk, hogy hol a webroot – márpedig sok hibaüzenet megmondja – akkor beírhatunk a webrootba egy fájlt amit aztán a böngészőn keresztül meghívhatunk. Ha ide be tudunk írni egy futtatható fájlt (mint egy php file) akkor abba azt teszünk amit akarunk és simán egy böngészőbeli url hívással futtathatjuk.
Fájlok olvasásánál az egyik célpont nagy valószínűséggel a /etc/passwd file lesz. Aztán a támadó keresgélhet log fileokban, history fájlokban szintén jelszavakra vadászva. Kíváncsi lehet adatbázis fájlokra amelyek sok érzékeny adatot tartalmazhatnak.
Ha az alkalmazás automatikusan hozzátűz egy kiterjesztést a megadott fájl névhez, akkor ugye azt hihetnénk, hogy a /etc/passwd.php hívás sikertelen lesz, mert nem létezik ilyen file. Azonban ha a megadott string végére hozzáteszünk egy null karaktert, akkor már egy passwd%00 vagy passwd%0a hívás sikeres lehet, mert a shell le fogja vágni azt a részt ami a null karakter után van.
A sebezhetőség elleni védekezés
- Ha a meghívandó fájl egy
select
-ből érkezik ne feltételezzük, hogy az adat nincs megpiszkálva, hanem ellenőrizzük vissza a szerver oldalon, hogy a felhasználónak van-e joga elérni a kért erőforrást. - Általánosságban is kerüljük az ilyen url, post alapú használatot. Ha a kiszolgálandó fájl a webrooton belül van, akkor van saját url-je.
- Ne próbálkozzunk a gyanús tartalmú fájlnevek tisztogatásával. Ha gyanús dobjuk el.
- Érzékeny alkalmazások esetében használjunk chroot környezetet
- Logoljunk minden gyanús kísérletet és bizonyos szám után küldjünk riasztást
Jócikk, bár én mindig szeretem azt hinni hogy a fejlesztőknek van maguktól is ennyi esze hogy ezeket a hibákat nem követik el.
Úgytűnik előfordul, hogy mégsincs 🙂