Bezpečnost | Seznam.cz | E-mail

Seznam měl vážnou chybu ve svém e-mailu. Útočník se mohl dostat do schránek uživatelů

E-mailová služba od Seznamu měla vážnou bezpečnostní trhlinu, která umožnila vniknout do cizích e-mailových schránek. Pokud byl uživatel ve svém prohlížeči k účtu Seznamu trvale přihlášen, mohl útočník získat balíček dat, který toto přihlášení v prohlížeči udržoval (cookie) a následně se k uživatelskému účtu přihlásit. 

Chybu objevil Marek Tóth, který se hledáním chyb v softwaru věnuje i profesně. V tomto případě šlo sice o mimopracovní záležitost, přesto velmi významnou. Zranitelnost nejprve nahlásil Seznamu a ten ji už opravil, nyní nám proto mohl poskytnout detailní informace o technickém postupu, jak tuto bezpečnostní díru objevil a jak se dala zneužít. 

Z pohledu napadeného uživatele stačilo kliknout na podstrčený odkaz. Ať už by byl nastražen v e-mailu, v postu na sociální síti nebo na nějakém webu, stačilo by prostě jen jednou kliknout (na jakémkoli systému a ve všech nejrozšířenějších prohlížečích). Útočník následně získá přístup do schránky a bez vědomí uživatele si zde může nejen přečíst poštu, ale třeba si zde zřídit i přesměrování příchozích e-mailů nebo vytvořit separátní přístup do schránky, jak je vidět v ukázkovém příkladu na videu:

Pokud máte e-mail u Seznamu a chcete se ujistit, že nebyl podobným způsobem napaden, zkontrolujte si v nastavení pravidla a také funkci sdílení schránky. Pokud by útočník chtěl šmírovat vaše e-maily, bezesporu by využil těchto funkcí, které mu umožní přístup k vaší poště bez vašeho vědomí. 

Následuje popis objevu a prověření funkčnosti chyby přímo od autora. Ještě detailněji vše popisuje na svém blogu.


Autor: Marek Tóth

Při analýze komunikace webových aplikacích od Seznamu jsem si všiml, že u některých API endpointů (/api/v1/user/badge, /api/v1/users/profile, /api/v1/user/properties/lang...) jsou povoleny CORS požadavky, a to vždy pro domény spadající pod Seznam.

image.png

Kromě povolených domén byly akceptovány požadavky i z libovolné subdomény. Dle response hlavičky Access-Control-Allow-Credentials: true bylo možné zasílat všechny tyto požadavky i včetně cookies => CORS Misconfiguration.

image.png

U všech požadavků byla v response buď nezajímavá data nebo jen základní informace o uživateli. Při každém požadavku také vždy došlo k vytvoření další ds cookie.

  • ds cookie je persistent cookie sloužící k autentizaci přihlášeného uživatele na stránkách Seznamu - na všech stránkách se uživatel přihlašuje skrze svůj Seznam Email. V tomto videu vysvětluje Martin Haller jak tato cookie funguje. 

Dle pravidel prohlížeče není hlavička Set-Cookie v response přístupná pomocí javascriptu, takže krádež cookies tímto způsobem nebyla možná.

Jeden zajímavý požadavek ale probíhal ve chvíli, kdy byl uživatel již přihlášen k e-mailu, a přešel na stránku od Seznamu, kde ještě přihlášen nebyl. Například byl uživatel přihlášen k Email.cz a navštívil stránku Sport.cz. Pokud se tato situace vyskytla, tak došlo k automatickému přihlášení. Při této akci se posílal tento POST požadavek:

https://login.szn.cz/api/v1/autologin?service=sport&return_url=http%3A%2F%2Flogin.seznam.cz

Odpovědí na tento požadavek byl status code 303 SEE OTHER s následným přesměrováním na adresu login.seznam.cz/ticket/{vygenerovaná hodnota}:

https://login.seznam.cz/ticket/2%7CureKCTec770kN1BSVwBHUFVRRQ5BWhNSNxYNKkQQZn0SaCzBs3gpQTpyAHYqlo6qN6LYkX51O5a1DbbYjamjtLI

Odpověď na tento požadavek již byla se statusem 200 OK. V response opět došlo k vytvoření nových hodnot cookies a k vrácení základních údajů o uživateli. Celá komunikace vypadala následovně:

image.png image.png

Zajímavostí bylo, že tato unikátní URL s „ticketem“ měla platnost přesně 30 sekund a během této doby bylo možné tuto adresu opakovaně odeslat. Po této době došlo k zneplatnění odkazu a bylo nutné znovu poslat /api/v1/autologin požadavek. Další zajímavosti bylo, že tato URL nemusela obsahovat žádné cookies v requestu, a i přesto došlo k vykonání validního požadavku.

 

V odpovědi URL s ticketem byly základní informace o přihlášeném uživateli. Jednalo se konkrétně o jméno, příjmení a uživatelské jméno. Při běžném použití CORS Misconfiguration bylo tedy možné tato data krást. V případě úniku těchto dat by se nejednalo o vážnější problém a já cílil především na větší bezpečnostní riziko, zkoumal jsem komunikaci proto dále...

Nyní bylo nutné reálně využít té CORS Misconfiguration, tedy povolených dotazů z jakékoliv Seznam domény nebo subdomény. Samo o sobě není toto zjištění zneužitelné a bylo nutné nalézt zranitelnost XSS. Začal jsem tedy hledat... Vzpomněl jsem si na službu Sweb (základní webhosting zdarma od Seznamu, pozn. red.). Zkusil jsem tedy, jestli je povolená doména Swebu.

image.png image.png

Zkusil jsem tedy, jestli je povolená doména a subdoména Swebu. Vše bylo povolené! Hledat XSS už jsem tedy nemusel, měl jsem vše, co jsem potřeboval. Měl jsem k dispozici rovnou webhosting, kam jsem mohl nahrát HTML stránku se skriptem. Jako bonus chyběla na Swebu bezpečnostní hlavička X-Frame-Options. (Chyběly všechny bezpečnostní hlavičky, ale X-Frame-Options byla nejdůležitější, a to kvůli načtení stránky v iframu)

Exploit

Jak jsem uvedl v předchozí části, tak při „běžném“ použití CORS Misconfiguration se získávají data z response body (=krádež uživatelských dat z response přihlášeného uživatele) a obvykle vypadá javascriptový kód takto:

image.png

Při čtení mnoha CORS Misconfiguration reportů jsem neviděl jiné použití než s responseText. Tímto způsobem bych získal pouze základní data o uživateli, což by nemělo žádný velký dopad. Po delším zkoumání a přemýšlení, zda se nevydat jinou cestou, jsem na to nakonec přišel a běžný CORS exploit jsem trochu upravil. Budu-li pracovat s informací, že adresa s tiketem je znovu použitelná, tak stačila tato změna:

console.log(this.responseText);
console.log(this.responseURL);

Změnou z responseText na responseURL jsem schopen získat poslední URL po jakémkoli přesměrování (info). V mém případě jsem tedy získal URL s tiketem. Tím, že byla adresa znovu použitelná po dobu 30 sec a bylo ji možné odesílat bez cookies, tak jsem měl vše potřebné k získání cookies.

Nyní stačilo tuto adresu do 30 sekund předat na svůj server, kde bylo nutné znovu odeslat request. Tím, že byl požadavek odeslán ze serveru, ke kterému jsem měl přístup, tak jsem byl schopen získat response včetně hlaviček, především tedy hlavičky Set-Cookie.

Shrnutí postupu

  1. Na testdomena.sweb.cz vytvořím HTML stránku se skriptem, který se bude dotazovat API včetně cookies (/api/v1/autologin, withCredentials=true)
  2. Pokud je uživatel přihlášen (status 200), tak získám URL s tiketem (responseURL)
  3. URL s tiketem ihned odešlu na svůj server (30 sekundová platnost odkazu)
  4. Na serveru získám URL a odešlu z něj znovu GET request přes curl (není potřeba cookies)
  5. Z response získám hlavičku Set-Cookie - především ds cookie 🍪
  6. + Absencí bezpečnostní hlavičky bylo možné načíst celou sweb stránku v iframu

Ukázka úspěšného exploitu na videu:

Diskuze (25) Další článek: Záhadný kovový monolit neznámého původu, který našli v Utahu, zmizel

Témata článku: , , , , , , , , , , , , , , , , , , , , , , , ,