Často od technicky znalejších lidí slýchávám, že by email u československých poskytovatelů v životě neměli, jelikož mají strach o bezpečnost. Vždyť email je víceméně klíčem k celé naší digitální identitě.

A ono nelze se jim občas divit. Postačí, když se podíváme na přítomnost možnosti nastavení dvoufázového (2FA) ověření. Jediný známý československý freemail, který jej v nějaké podobě má, je snad jen Seznam.cz, který tuto možnost přidal v polovině roku 2018. Ačkoliv už v roce 2018 bylo na implementaci 2FA docela pozdě, tak se alespoň začalo něco ohledně 2FA dít a věci se pohnuly správným směrem. Není to žádná sláva a rozhodně by to šlo udělat lépe, ale v nějaké podobě je to stále lepší než v podobě žádné.

A ačkoliv má spousta lidí v dnešní době již emaily u zahraničních poskytovatelů, podíl schránek u domácích poskytovatelů rozhodně není zanedbatelný. Některé statistiky hovoří až o těžko uvěřitelných 85 %. Moje osobní analýza databází mých soukromých projektů mluví o nějakých 60 % (vzorek přibližně 8000 uživatelů). Ať už je pravda kdekoliv, můžeme z toho vyvodit, že to rozhodně není malé množství. Rozhodl jsem se tedy podívat, jestli se mi podaří najít nějaké bezpečnostní chyby, které nějakým způsobem přímo ohrožují uživatele těchto portálů.

A jak už název článku napovídá, jako první jsem se rozhodl podívat na portál Centrum.cz. Ten podle mně dostupných dat používá něco kolem cca 10-20 % uživatelů českého internetu.

Uživatelské rozhraní Centrum.cz

Jeden z prvních pohledů samozřejmě míří směrem k autorizaci uživatele. Na Centrum.cz bohužel nenajdeme možnost zapnout 2FA v jakékoliv podobě. Co se týče samotné autorizace, tak ke každému účtu se lze přihlásit skrze zadaný email a příslušné heslo. Centrum.cz dále umožňuje uživatelům ještě přiřadit ke svým účtům Facebook/Google+ účet a přihlašovat se přes něj. A právě zde bylo možné najít první kámen úrazu.

Chyba #1 – Account takeover skrze Facebook

Závažnost: Vysoká
Dopad: Account Takeover
Slabina: Cross-Site Request Forgery (CSRF)
Stránka s přihlášením do emailu Centrum.cz

Podíváme se, jak vlastně takové spárování účtu s Facebookovým účtem na Centrum.cz funguje.

Po přihlášení můžeme zamířit do nastavení účtu, kde najdeme možnost spárování účtu buď s Facebookovým nebo Google+ účtem.

Po kliknutí na tlačítko "Přihlásit se přes Facebook" se otevře dobře známé dialogové okno, vyzývající k přihlášení na Facebook a povolení sdílení určitých informací o účtu se společností provozující Centrum.cz.

Facebookové vyskakovací okno

Poté co klikneme na "Continue as xxx" se dialogové okno zavře a oba účty jsou úspěšně propojeny. Nyní se už nemusíme přihlašovat vyplňováním emailu/hesla a přihlašovat pouze kliknutím na tlačítko "Přihlásit přes Facebook".

Samozřejmě důležité je, jaká magie se děje při párování na pozadí. Na stránce s přihlašovacími tlačítky bychom našli  vložený následující JavaScript. Kromě extrémně užitečné funkce ego.url, která mě osobně pobavila, je pro nás zajímavá funkce statusChangeCallback.

JavaScript z webu https://user.centrum.cz/nastaveni/?op=social (14.5.2019)

Je očividné, že stránka používá Facebook SDK, které obstará získání FB autorizačního tokenu k danému uživateli. První vyskočí dialogové okno a zažádá o potvrzení přístupu od uživatele. Pokud uživatel přístup k datům povolí, vytvoří tento dočasný autorizační token a předá ho v odpovědi do funkce statusChangeCallback. Autorizační token se dá po určitou dobu (každý token má svou expiraci) využít pro získání dat o uživateli, pro kterého byl tento token vygenerován. Tento token poté přibalí do POST požadavku na adresu https://user.centrum.cz/facebook/pair.php, který obstará spárování aktuálního uživatele s uživatelem identifikovaným daným Access tokenem. Backend pak pravděpodobně použije tento autorizační token, aby zjistil identifikační informace o uživateli, kterému tento token náleží a provede spárování.

Podívejme se na to teď z pohledu útočníka. Co kdyby se nám podařilo nějak do tohoto požadavku na spárování dostat náš Facebookový token? Tím by došlo k propojení účtu oběti s naším Facebookovým účtem a my bychom tím získali přístup k danému účtu. Zaměřme se tedy na poslední požadavek.

Požadavek na spárování (Osekaný pro přehlednost)

Při odeslání jakéhokoliv požadavku na server user.centrum.cz přibalí browser všechny normální Cookies (=bez nastaveného SameSite atributu), které má pro danou stránku uložené. Cookies ve většině aplikací slouží právě k autorizaci uživatele na dané stránce. Z těchto Cookies server následně zjistí o jakého uživatele se jedná a provede u něj spárování s FB tokenem poskytnutým v těle tohoto požadavku.

Jak je zajištěno, že byl tento požadavek ke spárování odeslán právě ze stránky Centrum.cz?  Jednoduše není. Je potřeba brát v úvahu, že prohlížeče nedělají moc velký rozdíl v tom, z jaké stránky byl požadavek odeslán(*). Jak jsem zmínil výše, prohlížeč spokojeně k požadavku přibalí Cookies, které autorizují daného uživatele na stránce, k jakémukoliv požadavku který na danou stránku míří. Prohlížeče nemají šanci znát úmysl požadavku. Při tomto útoku působí prohlížeč jako takzvaný „zmatený zástupce“ (Confused Deputy).  Jediný způsob, jak poznat, kdy je požadavek odeslán z jiné stránky je hlavička "Origin", která v sobě obsahuje webovou  stránku, ze které byl požadavek odeslán.

Útokům, které využívají důvěry prohlížečů a útočí skrze speciálně vytvořené požadavky z jiné stránky, se obecně přezdívá Cross-Site Request Forgery Attacks (CSRF).

Jakákoliv webová stránka tedy může na tento koncový bod odeslat POST požadavek s Cookies uživatele například skrze HTML formulář. A jelikož zde chybí jakákoliv obrana proti podobným útokům, stačí když donutíme prohlížeč naší oběti odeslat tento požadavek na spárování s FB účtem a na pozici FB tokenu v požadavku dosadíme token patřící našemu Facebook účtu.

Pokud je tedy uživatel aktuálně přihlášen na Centrum.cz (má platné autorizační Cookies), může jakákoliv stránka, na kterou na internetu přistoupí, odeslat požadavek například skrze skrytý předvyplněný HTML formulář, který je následně automaticky skrze javascript odeslán. Jak by taková stránka mohla vypadat je možné vidět na následujícím obrázku.

Jednoduchý proof of concept

Zde máme jednoduchý formulář, který skrze Javascript odešle požadavek na spárování s předvyplněným tokenem. Jelikož potvrzení formuláře taktéž provede přesměrování na Centrum.cz, mohli bychom tuto stránku zobrazit v neviditelném Iframu a ten následně umístit na libovolnou webovou stránku. Poté uživatel ani nemá moc velkou šanci si něčeho nezvyklého všimnout a my bychom získali plný přístup k jeho Centrum.cz účtu. (Pokud nemá k účtu přiřazený svůj vlastní FB účet).

Jelikož Centrum.cz nemá žádný určený kontakt pro zasílání bezpečnostních zranitelností, chybu jsem nahlásil přes klasický helpdesk. Tým Centrum.cz jsem chtěl původně pochválit za rychlost opravy této chyby. K nasazení opravy došlo během 12 hodin od mého hlášení, bohužel byla oprava značně nedostačující. (Čehož jsem si bohužel všiml až o 2 měsíce při dopisování tohoto článku).

Možností bránit se proti těmto útokům je několik a podrobně se na ně podíváme třeba v některém z další článků. Nejčastěji je to ochrana skrze CSRF token, kontrolu hlavičky Origin, ochrana skrze specifický Content-Type nebo SameSite attributy u Cookies.

Chyba byla na straně Centrum.cz opravena přidáním takzvaného CSRF tokenu. Ten se používá, aby bylo zajištěno, že daný POST požadavek na spárování skutečně odeslala stránka Centrum.cz a nikoliv jiná. Stránka pro každého uživatele (v ideálním případě pro každou session) vygeneruje náhodný token. Ten pak nějakým způsobem předá (obvykle společně s obsahem stránky) uživateli a jeho hodnotu přidává do všech důležitých požadavků, které se odesílají zpět na server. Jelikož útočník nemá šanci jeho hodnotu zjistit, nemůže odeslat platný požadavek na spárování. V Centrum.cz při párování upravili předávaný Javascript a hodnotu tohoto předávají rovnou tam, kde je potřeba. Porovnejte opravený skript s tím, který sloužil ke spárování před "opravou" chyby.

JavaScript z webu https://user.centrum.cz/nastaveni/?op=social (16.5.2019)

Skutečně je k volání přibalen CSRF token. Otázkou je, zda je taktéž přidána jeho kontrola na straně serveru. Zkusíme odeslat požadavek s neplatným CSRF tokenem.

Odeslání požadavku s neplatným tokenem

Můžeme vidět, že server správně ověřil, že je token neplatný a vrátil chybovou hlášku (400 Bad Request).

Problém v implementaci tokenů na straně Centrum.cz byl trošku někde jinde. Jak jsem již zmínil, aby byla ochrana skrze CSRF tokeny účinná, útočník nesmí mít možnost se k tokenu uživatele jakkoliv dostat. Generování tokenů na Centrum.cz však všem uživatelům přidělovalo vždy stejný token. Díky tomu nebylo pro útočníka nikterak složité zjistit hodnotu tohoto tokenu a upravit dle toho odeslaný požadavek. Viz upravený Proof of concept.

Upravený proof of concept obcházející zabezpečení proti CSRF

Po upozornění na chybu v generování tokenů byla rychle ze strany Centrum.cz nasazena další úprava kódu. CSRF tokeny se nyní již unikátně generovaly dokonce pro každý jednotlivý požadavek.

Bohužel však nebylo jakkoliv zajištěno, zda token, který je vygenerován pro uživatele X není použit uživatelem Y. Útočník si tedy mohl vygenerovat svůj token a použít jej, aby jím podepsal požadavky případných obětí.  

Po několika dalších emailech s podporou Centrum.cz došlo k vyřešení i tohoto nedostatku a tím i dostatečnému zabezpečení funkcionality pro párování účtů.

Timeline
-> 15.05.2019 01:41: Chyba nahlášena
<- 15.05.2019 13:19: "Oprava" chyby skrze přidaný CSRF token, poděkování.
-> 16.07.2019 23:23: Nahlášena chyba v generování CSRF tokenů
<- 17.07.2019 11:12: Oznámení o nasazení opravy
-> 17.07.2019 13:56: Snaha o vysvětlení, že je stávající implementace stále nedostačující (tokeny se generují, ale špatně ověřují)
<- 17.07.2019 15:15: Oznámení, že problém by měl být vyřešen.
~~~ Vysvětlování proč stávající implementace stále není dostačující ~~~
<- 22.07.2019 11:57: Oznámení, že problém by měl být konečně vyřešen.
-> 22.07.2019 12:28: Potvrzení opravy.
~~ 25.07.2019 12:15: Zveřejnění tohoto článku

(*) - Prohlížeče k POST požadavku mířícímu z jiného webu nepřibalí žádné Cookies, které jsou označeny atributem "SameSite" s hodnotou Lex nebo Strict. Navíc nastavení Lex bude v budoucnu například v Chrome výchozím nastavením, čímž podobné útoky nebudou za normálních okolností možné.

V příštím díle ještě zůstaneme u Centrum.cz a podíváme se, v jakých případech se mohou i z jednoduchých znaků pro odřádkování stát bezpečnostní problémy.