Detail přednášky

O návrhu zabezpečení aplikací pomocí více úrovní ochrany. Protože když na něco zapomenete, tak by to pro uživatele nebo aplikaci neměl být game over.

V přednášce zmiňuji i Content Security Policy, ale věnujeme se jen novinkám v CSP Level 3. Obecněji probírám Content Security Policy v přednášce XSS PHP CSP ETC OMG WTF BBQ.

Přijďte si o ochraně proti zákeřnému JavaScriptu popovídat na školení Bezpečnost webových aplikací (14. 6. 2017 Praha).

Datum a akce

30. 11. 2016, PHP live (délka přednášky 50 minut, 33 slajdů, video)

Slajdy

JavaScript: The Good Parts × JavaScript: The Definitive Guide

#1 JavaScript má své stinné stránky a bude jich asi docela dost, soudě podle tloušťky těchto dvou knih. Ukážeme si, jak se špatného JavaScriptu na webu zbavit a jak se pojistit pomocí více úrovní ochrany, kdybyste na to náhodou zapomněli.

XSS (Cross-Site Scripting)

#2 Princip více úrovní ochrany se dá pěkně vysvětlit na Cross-Site Scriptingu. To je útok, který útočníkům slouží ke spuštění zákeřného JavaScriptu staženého třeba z jiného serveru v kontextu zranitelné aplikace. Tím mohou zaútočit na uživatele i jejich prohlížeče.

@osvdb replying to @jeremiahg: what is the first published XSS vuln that you are aware of? (e.g. in a specific product) 1999-07-09 according to our list

#3 Cross-Site Scripting (XSS) není žádná novinka. Podle Open Sourced Vulnerability Database byla první XSS zranitelnost publikována v roce 1999. Samotný název „Cross-Site Scripting“ ale vznikl až v lednu 2000 v Microsoftu.

$1.2 million

#4 Jen v letech 2014–2016 vyplatil Google 1,2 milionu USD na odměnách za nalezení XSS chyb ve svých aplikacích v rámci jejich Vulnerability Reward Programu. To je průměrně 50 tisíc dolarů měsíčně, za hlášení chyb z minulého tisíciletí to docela jde.

Krabice od vína plná peněz

#5 Jen pro zajímavost, na obrázku vidíte muže, vlevo, a milion dolarů ve stodolarových bankovkách, alespoň podle PageTutoru. To by se skoro vešlo do nějaký krabice od vína, co? Tak zhruba tolika penězi Google za 2 roky odměnil úspěšné nálezce XSS chyb.

Zombie

#6 Cross-Site Scripting je takovej malej nemrtvej. Myslíte si, že jste ho zabili, ale on se vám při dalším releasu vrátí a ani o tom nevíte.

Label: [<script>alert('XSS');</script>]

#7 Pojmenovávání věcí je jedním ze dvou nejtěžších problémů v počítačových vědách (tím druhým je invalidace cache) a když nevím, tak píšu alert(…). Můj SSH klíč je sice můj dobrý kamarád, ale přesto bych nevěděl, jak jinak ho pojmenovat. A někdy když nevím, tak se pak tvářím překvapeně, třeba jako v případě těchto dvou obálek od CZ.NICu.

<div><script>alert('XSS');</script></div>

#8 Trochu překvapeně jsem se tvářil i v tomto případě. Do HTML kódu se název SSH klíče vypsal přesně tak jak jsem ho zadal.

The page at https://bitbucket.org says: XSS

#9 V prohlížeči se alert('XSS') opravdu spustil. Kdybych si na Bitbucketu založil tým a pozval do něj uživatele, tak by se jim při přidávání SSH klíčů v jejich prohlížečích spustil můj JavaScript, kterým bych mohl zobrazit například falešné políčko pro zadávání hesla. Atlassian mě za nahlášení této chyby zařadil do své síně slávy.

BeEF (The Browser Exploitation Framework Project)

#10 Jenže XSS je mnohem víc než jen alert('XSS'). XSS framework BeEF má zhruba 300 vestavěných modulů, které v browseru umí zobrazit např. falešné notifikace, falešné přihlašovací formuláře, umí udělat screenshot stránky nebo přehrát MP3. Na PHPlive jsem ho ukazoval v jedné z předchozích přednášek.

2nd line of defense

#11 Vývojáři často zapomínají ošetřit speciální znaky jako <, >, ", ' a asi budou zapomínat i nadále. Protože mají hořící termíny, špatný kafe nebo moc piv. Takže potřebujeme tohle, víc úrovní ochrany a obrany.

"Don't worry, I gotcha"

#12 Další úrovně zabezpečení nemusí fungovat vždy a pro všechny uživatele, ale když první úroveň selže, tak vám další vrstva může zachránit život. Nebo cookies. Když se náhodou něco stane, tak pána v červeném tričku může zachránit chlapík v modrém tričku. Tahle druhá úroveň není z nejlepších, ale aspoň tam je, že.

password_hash() a password_verify()

#13 Takovou poměrně běžnou (kéž by!) úrovní ochrany je i hashování hesel. První úroveň (zabezpečení přístupu k databázi) selhává poměrně často a tak musí nastoupit další vrstva. Ale ani hashování neuchrání všechna hesla, velmi jednoduchá hesla jdou cracknout i při použití doporučovaných funkcí, v PHP to jsou password_hash() a password_verify().

4x ATI R9 290 speed: 156 H/s

#14 Dean Pierce zkusil crackovat prvních 6 milionů hashů (z celkem 36 milionů) z databáze Ashley Madison. Hesla byla hashována pomocí bcryptu s parametrem cost = 12. Jeho stroj s 4× GPU ATI R9 290 dokázal generovat jen 156 kombinací za sekundu.

4000 cracked passwords over the course of 5 days

#15 I přesto, že hesla byla hashována velmi dobře (bcrypt, cost = 12), tak se Deanovi za 5 dní podařilo cracknout 4 tisíce hesel. Druhá úroveň ochrany, v tomto případě tedy hashování hesel, nefunguje pro všechny uživatele, ale to nevadí. Pro ostatní funguje skvěle, a tenhle příklad to hezky ukazuje.

123456 password 12345 qwerty 12345678 ashley baseball abc123 696969 111111 football fuckyou madison asshole superman fuckme

#16 Tohle je 16 nejčastějších hesel z těch 4 tisíc, které se mu podařilo cracknout. Vcelku předvídatelná sestava, alespoň na seznamku pro zadané.

Krádež cookies za bílého dne

#17 XSS se asi nejčastěji používá ke krádeži cookies z browseru, dneska to dokáže už i králík. Vám k tomu stačí 1–2 řádky JavaScriptu.

XSS Auditor

#19 Další druhá úroveň ochrany je zabudované přímo ve vašem prohlížeči, zvlášť pokud používáte Chrome, Internet Explorer nebo Edge. Ve Firefoxu není, ale to nevadí, není to primární úroveň ochrany. XSS auditor (XSS filtr) chrání proti Reflected XSS.

>:| → 1 → :-) → 2 → web → 3 → :-)

#20 Takto Reflected XSS funguje. Útočník pošle uživateli odkaz s nějakým zákeřným JavaScriptem v URL (1), uživatel na odkaz klikne a prohlížeč pošle požadavek na webovou aplikaci (2). JavaScript z požadavku se vloží do stránky a vše se pošle zpět uživateli (3), v jehož prohlížeči se ten JavaScript spustí. Browser vidí, co se mu vrátilo z aplikace a pokud to vypadá jako JavaScript, který v požadavku odeslal, tak spustí XSS filtr, pokud ho prohlížeč má a je povolen.

X-XSS-Protection: 1; mode=block

#21 XSS filtr můžete ovládat ze serveru poslanou hlavičkou X-XSS-Protection. Režim mode=block byste měli používat, prohlížeč po aktivaci filtru stránku vůbec neukáže. Režim mode=block je defaultně zapnutý v Chrome od verze 57. Starší verze se pokouší stránku vyčistit. Na mém testovacím webu si můžete XSS auditor vyzkoušet, Chrome vám zobrazí chybu ERR_BLOCKED_BY_XSS_AUDITOR a vypíše upozornění do konzole.

Response Headers: Content-Security-Policy

#22 Content Security Policy (CSP) je nejnovější přírůstek v řadě druhých úrovní ochrany proti XSS. Tato hlavička posílaná ze serveru určuje povolené URL, ze kterých prohlížeč do stránky může stahovat obrázky, JavaScript, CSS a další. Takže i když útočník dokáže do HTML vložit značku <script>, tak browser z uvedené adresy nestáhne kód, pokud ta adresa není povolená.

Content-Security-Policy: default-src 'self'

#23 CSP jsem se věnoval v jedné z předchozích přednášek na PHPlive, takže jen malé opáčko, ke kterému navíc dostanete souhrn novinek z CSP3. Toto je asi nejjednodušší varianta hlavičky Content-Security-Policy. Povolí browseru do stránky poslané s touto hlavičkou načítat JavaScript, obrázky, CSS a další pouze ze 'self', tedy z aktuálního protokolu, domény a portu (origin).

Content-Security-Policy: default-src 'self'; img-src 'self' https://www.google-analytics.com; script-src 'self' https://www.google-analytics.com 'unsafe-inline'

#24 Můžeme navíc povolit načítání obrázků a skriptů z https://www.google-analytics.com, aby fungoval skript Google Analytics. Navíc pomocí unsafe-inline povolíme tzv. inline JavaScript, to je veškerý kód, který je napsán přímo ve stránce mezi značkami <script> a </script>, v onclick handlerech apod. Spousta nástrojů unsafe-inline potřebuje, patří mezi ně i Google Tag Manager, jenže jakmile unsafe-inline povolíte, tak se nastavená politika dá jednoduše obejít.

Content Security Policy Level 3

#25 Situaci vylepšuje CSP3 a 'strict-dynamic'. To je direktiva, kterou Google do CSP přidal na základě zkoumání nastavení Content Security Policy na cca 1,6 milionu webů. Díky 'strict-dynamic' bude prohlížeč ignorovat seznam povolených domén a bude stahovat jen skripty označené pomocí nonce, ty navíc mohou vkládat další skripty bez potřeby rozšiřovat politiku.

Content-Security-Policy: script-src 'strict-dynamic'

#26 Direktivu 'strict-dynamic' podporuje Chrome i Firefox, oba shodně od verze 52. Vyzkoušet si ji můžete na mé testovací stránce. Pojďme si takovou bezpečnou CSP hlavičku sestavit, po přidání 'strict-dynamic' musíme povolit skripty označené pomocí nonce.

<script src=… nonce="rAnd0m123"></script>

#27 Atribut nonce slouží pro označení skriptů. Jeho hodnota by se měla při každém načtení stránky změnit a měla by být minimálně 16 náhodných bajtů zakódovaných do Base64. Stejný nonce může být použit k označení více skriptů na jedné stránce. Pro generování nonce můžete použít můj nonce-generator.

Content-Security-Policy: script-src 'strict-dynamic' 'nonce-rAnd0m123'

#28 Pomocí 'nonce-<nonce>' do hlavičky Content-Security-Policy přidáme hodnotu atributu nonce ze značky <script>.

Content-Security-Policy: script-src 'strict-dynamic' 'nonce-rAnd0m123' 'unsafe-inline' http: https:;

#29 Pokračujeme takto: starší prohlížeče bez podpory 'strict-dynamic' načtou skripty označené pomocí atributu nonce a ty pak mohou dále načítat skripty z http: a https:, tedy prakticky jakékoliv další. Nakonec je potřeba povolit i inline JavaScript pro prohlížeče, které nepodporují ani nonce z CSP2. Content Security Policy není primární metodou obrany proti XSS, tou je stále převod nebezpečných znků na entity, takže nevadí, že pořádně bude fungovat jen pro uživatele moderních prohlížečů s podporou CSP3.

Content-Security-Policy: script-src 'strict-dynamic' 'nonce-rAnd0m123' 'unsafe-inline' http: https:; object-src 'none'; base-uri 'none';

#30 Nakonec zakážeme načítaní pluginů, jako např. Flashe, a použití značky base pro určení base URL stránky. Pomocí obojího lze Cross-Site Scripting spáchat také.

Content-Security-Policy: script-src 'strict-dynamic' 'nonce-rAnd0m123' 'unsafe-inline' http: https:; object-src 'none'; base-uri 'none'; report-uri https://report-uri.io/…

#31 Pokud by se prohlížeč pokusil načíst nějaký zdroj, který mu Content Security Policy zakazuje, tak vám o tom může poslat report na adresu v report-uri a vy tak můžete případnou chybu opravit. Jenže prohlížeče posílají spoustu reportů aniž byste v aplikaci nějakou chybu měli, protože lidé používají divná rozšíření, viry nebo různé free Wi-Fi, které do stránek vkládají reklamu. Než číst každý jednotlivý report, tak je lepší koukat na grafy a trendy. Obojí vám hezky zobrazí například report-uri.io.

CSP ✔ (csp-evaluator.withgoogle.com)

#32 Nasazení CSP není jednoduché. Politika často musí být vcelku otevřená, je nutné povolit spoustu originůinline JavaScript. Tím se také zvyšují šance pro útočníka, že najde skulinku, kterou bude moci vložit svůj kód. Nastavení CSP si můžete otestovat v nástroji CSP Evaluator, prozradí vám, jak by šlo konkrétní politiku obejít.

HTTP-Only cookie, XSS Auditor, Content Security Policy, observatory.mozilla.org

#33 Úrovní obrany nejen proti XSS je více, naučte se ovládat všechny. Kontrolu nastavení některých z nich vám oznámkuje Observatory by Mozilla. Mimochodem, boj s Cross-Site Scriptingem neutichá a vývojáři se snaží stále vymýšlet nové experimentální zbraně, např. koncept Isolated Scripts.

Video záznam

https://www.youtube.com/watch?v=QVwT9IYRjWE

English