Protokol HTTP je protokolem bezstavovým. To znamená, že každý request, který směřuje ze strany uživatele na webový server, je naprosto samostatný a soběstačný. Webový server si nijak nepamatuje předchozí stavy. Server vždy pouze vyřídí aktuální požadavek uživatele a po odeslání odpovědi tuto komunikaci okamžitě zapomene. Pokud uživatel potřebuje být při komunikaci přihlášen, musí se oproti serveru autentizovat s každým novým requestem. Bez externích mechanismů by to v praxi znamenalo, že by uživatel musel s každým svým požadavkem odesílat na server také své uživatelské jméno a heslo. Jak jistě chápete, neslo by toto s sebou rizika spojená s možným odposlechem a jinými útoky, které by se pokoušely takto přenášené přihlašovací údaje odcizit. Programovací jazyky proto zavádí sessions (relace), díky nimž se uživatel přihlásí pouze jedenkrát. Server po přihlášení vygeneruje náhodný session identifikátor (dále pouze SID), který si jednak zapamatuje, a jednak jej předá uživateli, aby se ten tímto identifikátorem nadále autentizoval. V případě PHP si server uloží vygenerovaný SID do úložiště sessions na filesystém jako soubor, který bude v defaultním nastavení PHP pojmenován prefixem sess_ a vygenerovým SID.
Společně s odpovědí pak server odešle uživateli HTTP hlavičku Set-Cookie, která při defaultním nastavení serveru ponese hodnotu PHPSESSID=vygenerované_SID.
Jakmile webový prohlížeč uživatele obdrží tuto odpověď, uloží si na základě HTTP hlavičky Set-Cookie předané hodnoty do úložiště cookies a přiřadí si je ke konkrétní doméně, která mu tuto hlavičku zaslala.
Soubor, který si aplikace na straně serveru uložila do úložiště sessions, bude následně používán pro ukládání session proměnných. Ty mohou být ze strany aplikace ukládány takto:
$_SESSION["name"]="My Name";
Pokud tedy uživatel odešle na server své přihlašovací údaje, a server uživatele autentizuje, pak se vytvoří relace a server si do session proměnných uloží například id uživatele, jeho jméno a případně i jeho uživatelská práva.
Když následně uživatel odešle na stranu serveru další request, bude společně s ním předána serveru webovým prohlížečem automaticky také HTTP hlavička cookie, která bude obsahovat hodnoty všech cookies, které má webový prohlížeč pro danou doménu uloženy.
Pokud webová stránka na straně serveru obsahuje volání funkce session_start(), načte server z úložiště relací session soubor, který obsahuje název se stejným identifikátorem, jako přišel v hodnotě cookie PHPSESSID. Obsahem tohoto souboru si prohlížeč naplní superglobální pole $_SESSION[] uloženými session proměnnými.
Následně se aplikace již může podle obsahu session proměnných rozhodovat, zda se uživatel již v minulosti autentizoval, o koho se jedná a jaká má tento uživatel privilegia.
Pro tento typ útoku je potřeba splnit požadavek na možnost spouštění vlastních PHP skriptů útočníkem na straně webového serveru. Tento typ útoku bude proto útočníky využíván převážně na sdílených serverech webhostingu.
Samotný útok je pak možné rozdělit do několika fází:
Takto bude vypadat úložiště session souborů na straně serveru:
sess_1fd1jtmnbudtb1t9k31rlontq7 obsah: prázdný
Takto bude vypadat úložiště cookies v prohlížeči útočníka:
mypage.hosting.xx PHPSESSID 1fd1jtmnbudtb1t9k31rlontq7
Takto bude vypadat úložiště session souborů na straně serveru:
sess_1fd1jtmnbudtb1t9k31rlontq7 obsah: prázdný
sess_hvmuld3jacojvl6lplar7b4fl1 obsah: customer_id=123
Takto bude vypadat úložiště cookies v prohlížeči útočníka:
mypage.hosting.xx PHPSESSID 1fd1jtmnbudtb1t9k31rlontq7
eshop.hosting.xx PHPSESSID hvmuld3jacojvl6lplar7b4fl1
Takto bude vypadat úložiště session souborů na straně serveru:
sess_1fd1jtmnbudtb1t9k31rlontq7 obsah: prázdný
sess_hvmuld3jacojvl6lplar7b4fl1 obsah: customer_id=123
Takto bude vypadat úložiště cookies v prohlížeči útočníka:
mypage.hosting.xx PHPSESSID hvmuld3jacojvl6lplar7b4fl1
eshop.hosting.xx PHPSESSID hvmuld3jacojvl6lplar7b4fl1
Array
(
[customer_id] => 227
)
Takto bude vypadat úložiště session souborů na straně serveru:
sess_1fd1jtmnbudtb1t9k31rlontq7 obsah: prázdný
sess_hvmuld3jacojvl6lplar7b4fl1 obsah: customer_id=98
Takto bude vypadat úložiště cookies v prohlížeči útočníka:
mypage.hosting.xx PHPSESSID hvmuld3jacojvl6lplar7b4fl1
eshop.hosting.xx PHPSESSID hvmuld3jacojvl6lplar7b4fl1
V případě útoků na cloudové aplikace, kdy všechny webové aplikace na serveru mají stejnou programovou strukturu – liší se pouze svým vzhledem (skinem), není potřeba, aby měl útočník k dispozici možnost spouštění vlastních PHP skriptů. Průběh útoku na cloudovou službu poskytující zákazníkům například e-shopy, by mohl vypadat následovně:
Takto bude vypadat úložiště session souborů na straně serveru:
sess_ kbg196j2d3rrvuk7ihlqlbbfp1 obsah: customer_id=93
Takto bude vypadat úložiště cookies v prohlížeči útočníka:
eshop1.cloud.xx PHPSESSID kbg196j2d3rrvuk7ihlqlbbfp1
Takto bude vypadat úložiště session souborů na straně serveru:
sess_ kbg196j2d3rrvuk7ihlqlbbfp1 obsah: customer_id=93
Takto bude vypadat úložiště cookies v prohlížeči útočníka:
eshop1.cloud.xx PHPSESSID kbg196j2d3rrvuk7ihlqlbbfp1
eshop2.cloud.xx PHPSESSID kbg196j2d3rrvuk7ihlqlbbfp1
.cloud.xx PHPSESSID kbg196j2d3rrvuk7ihlqlbbfp1
Tento typ útoku je víceméně shodný s předchozím. Jediný rozdíl bude v tom, že si útočník zaregistruje na stejném cloudovém serveru svůj vlastní e-shop. Díky vlastnictví e-shopu bude mít tento uživatel administrátorská práva, a aplikace si tak například uloží tuto informaci do session proměnné isAdmin.
Po zkopírování cookie pro jiný e-shop a po následné návštěvě tohoto jiného e-shopu, bude mít útočník administrátorská práva i na tomto jiném e-shopu.
Každý programátor má své zažité postupy při použití session proměnných. Pokud například jeden autor vytvoří web s autentizací a použije pro držení informace o přihlášení uživatele session proměnnou isLogged pak s největší pravděpodobností bude i jiná jeho aplikace držet tuto informaci ve stejně pojmenované session proměnné. Pokud pak takovýto vývojář provozuje své webové aplikace na jednom serveru (například na vlastním VPS) pod stejným uživatelským účtem a se sdíleným úložištěm session, bude pravděpodobně možné provádět authentication bypass stejným způsobem i mezi těmito zcela odlišnými aplikacemi.
Ačkoliv jsme si výše uváděli příklady funkční pouze na PHP, hrozí stejné typy útoku i na jiných platformách (např. Java, .Net, apd.), kde se session na straně serveru ukládají do paměti. Střetl jsem se s cloudovými službami, kde se útočník mohl stát uvedeným postupem administrátorem všech hostovanch e-shopů, přestože byla aplikace vytvořena v Javě. Jak je to možné? Cloudová aplikace může v některých případech běžet pouze jedna jediná pro všechny hostované služby. Podle subdomény se mění pouze vzhled této aplikace, který je uložen ve formě dat například v databázi. Tato aplikace a tím pádem i všechny hostované služby pak opět sdílí jedno úložiště pro sessions, a to i v případě, kdy je toto úložiště umístěno v paměti, kde každá aplikace (v tomto případě je jen jedna) využívá svůj vlastní paměťový prostor.
Administrátoři webových serverů mají k dispozici následující způsoby obrany.
Na Kafemlejnek.tv jsme si na téma této zranitelnosti povídali s Honzou Novotným a Petrem Ferschmannem. V závěrečné fázi videa jsou zachyceny také ukázky všech zde popisovaných typů útoků.
V případě zájmu o vyzkoušení si neoprávněného přístupu do administrace cizích e-shopů můžete navštívit Proof of Concept dostupný na adrese www.sharedsessions.cz.