Podívejte se raději na online verzi přednášky, slajdy mohly být aktualizovány nebo doplněny.

Detail přednášky

Moderní HTTP browsery umí mnohem víc věcí, než jen zobrazit stránku nebo HTML. Třeba je ve správnou chvíli vůbec nezobrazit. Přijďte a já vám ukážu, jak zabránit průšvihu alespoň v browseru, když už to na serveru nezvládnete.

Pořádám školení Bezpečnost webových aplikací (nejbližší termín: termín zatím nevypsán), přijďte!

Datum a akce

12. května 2016, PHP live //spring Žilina (délka přednášky 60 minut, 18 slajdů, video)

XFO XCTO XXP SRI OMG WTF BBQ (Překlad: HTTP hlavičky, Subresource Integrity a spol.)

#1 Přednáška o všech těchto zkratkách, za kterými se skrývají bezpečnostní HTTP hlavičky a atributy.

https://securityheaders.io

#2 Některé HTTP hlavičky mohou vaše návštěvníky a zákazníky uchránit před chybou, kterou jste udělali. Bezpečnostní hlavičky nejsou primární obrana, ale mohou snížit dopad útoku, který využil například chybějící ošetření uživatelského vstupu. Na securityheader­s.com (dříve securityheader­s.io) si otestujte váš web, jak moc a které bezpečnostní hlavičky používá.

A a A+

#3 Výsledná známka by měla být A nebo ještě lepší A+, podobně jako u HTTPS testu SSL Labs. Pokud máte R tak to znamená Redirect a musíte ještě jednou kliknout pro přesměrování na cílovou stránku a známku. Tak co, jakou máte?

( ► )

#4 Pojďme si představit jednotlivé hlavičky a ukázat problémy, kterým mohou zabránit. Provozujete anketu nebo soutěže, ve kterých se sbírají lajky a ten kdo má lajků nejvíc vyhrává? Prý existuje herní mafie, která všechny podobné soutěže vyhrává. Jeden ze způsobů, jak by mohla ovlivňovat výsledky anket se nazývá Clickjacking nebo UI redress attack. Stačilo by na Facebook umístit odkaz na stránku s lákavým obsahem a před něj správně napozicovat vaši anketu v průhledném iframe.

https://exploited.cz/frames/

#5 Vyzkoušejte si to: podívejte se na výsledky ankety o běhání, zapamatujte si stav předposlední možnosti a pak na mém webu klikněte na tlačítko ►. Před tlačítkem je správně napozicovaný průhledný iframe s vloženou anketou, takže vlastně kliknete „do ankety“. Vše bude jasné, když iframe uděláme poloprůhledný a vy najedete myší na ono tlačítko. Uvidíte titulek „Přidat hlas pro …“. Pokud máte zaplý ad-blocker, tak tlačítko ► nejspíš nebude na tom správném místě, zkuste to bez blokování reklam. Jako uživatelé se můžete bránit instalací rozšíření NoScript pro Firefox.

X-Frame-Options: SAMEORIGIN, X-Frame-Options: DENY

#6 Podobným trikům zabráníte posláním hlavičky X-Frame-Options (XFO), s hodnotou SAMEORIGIN (stránka posílající hlavičku půjde vložit do iframe, pokud iframe bude na stejné doméně, protokolu a portu jako ta stránka) nebo DENY (stránka do iframe vložit nepůjde). V konfiguraci Nette nastavte http: frames: false, framework pak pošle X-Frame-Options: DENY automaticky.

Content Security Policy: frame-ancestors 'none'

#7 Pomocí Content Security Policy můžete nastavit seznam stránek, do kterých je možné váš web vložit pomocí direktivy frame-ancestors, hodnota 'self' je stejná jako X-Frame-Options: SAMEORIGIN, 'none' pak odpovídá X-Frame-Options: DENY. Pro určení jiné domény pomocí hlavičky X-Frame-Options sice existuje hodnota ALLOW-FROM, ale umožňuje uvést pouze jednu kombinaci domény, protokolu a portu (origin) a nepodporuje ji Chrome, použijte raději CSP a frame-ancestors.

Content-Security-Policy

#8 Hlavička Content-Security-Policy zaručí, že browser bude do stránky načítat zdroje jako např. obrázky, fonty, JavaScript a další pouze z předem povolených umístění. Je to další vrstva obrany proti útoku Cross-Site Scripting, která může zabránit například spuštění JavaScriptu, který útočník do stránky vložil pomocí značky <script>. Nastavení Content Security Policy může být na každé stránce jiné, v administraci může být přísnější, než na veřejném webu. Popis direktiv a použití najdete v moji přednášce o CSP. Pokud budete chtít implementovat dynamické CSP v Nette, tak sledujte vývoj balíčku spaze/csp-config.

Content-Security-Policy-Report-Only: default-src https:; report-uri …

#9 Content Security Policy vám taky pomůže najít tzv. mixed content. To je JavaScript a obrázky a další obsah načítaný z HTTP do stránky, kterou prohlížeč stáhl po HTTPS. Touto hlavičkou povolíte načítání pouze z HTTPS, ale browser bude jen posílat reporty, pokud na mixed content narazí. JavaScript ale přesto normálně spustí a obrázky zobrazí. Reporty si posílejte do služby report-uri.com.

Strict-Transport-Security: max-age=31536000; includeSubDomains;

#10 Tato hlavička, HTTP Strict Transport Security (HSTS), zajistí, že se vaše stránka po následujících X vteřin (zde 31536000, přibližně jeden rok) bude načítat jenom po HTTPS. I když uživatel do prohlížeče napíše adresu začínající na http://, tak prohlížeč požadavek interně přesměruje na https://, pokud o webu ví, že HSTS podporuje. Parametr includeSubDomains znamená, že se toto interní přesměrování bude vztahovat i na všechny poddomény od té úrovně, která HSTS hlavičku nastavila. Dávejte si na to pozor, nastavte pro začátek menší počet sekund, třeba pár minut a postupně to zvyšujte. Pokud si prohlížeče návštěvníků zapamatují, že váš web běží jen na HTTPS, tak nemůžete jen tak přejít zpět na HTTP. Při použití includeSubDomains musíte pamatovat na to, že všechny subomény musí podporovat HTTPS. To bývá někdy problém pro služby třetích stran, které ale běží na vaší doméně, typicky třeba blog.něconěk.de. HSTS s takhle dlouhým max-age přidejte, až budete mít HTTPS dobře otestované, ne rovnou na začátku. Hlavička by do browseru měla dorazit jenom po šifrovaném spojení HTTPS. O důvodech, proč a jak HSTS použít se dozvíte v přednášce věnované HTTP Strict Transport Security.

X-Content-Type-Options: nosniff

#11 Mohou uživatelé na váš web nahrávat nějaký obsah? Třeba textové soubory, s příponou .txt a MIME typem text/plain, které ale obsahují JavaScript? Některé browsery, například jindy poměrně zásadový Chrome, v takovém případě obsah očmuchá a když se mu zdá, že to je JavaScript, tak s tím tak naloží a spustí ho. To může být nebezpečné, zvlášť pokud soubory od uživatelů jsou na stejné doméně jako samotná aplikace. Chrome se tím pokouší řešit špatné nastavení serverů, které posílají chybné MIME typy. Lepší je správně nastavit server, než nechat prohlížeč něco odhadovat. Hlavička X-Content-Type-Options by měla přijít společně s obsahem, u kterého chceme očmuchávání vypnout, ne se stránkou, do které se vkládá. Vyzkoušejte si to na https://exploited.cz/content/ a sledujte konzoli browseru.

HTTP Public Key Pinning (HPKP), Public-Key-Pins

#12 Hlavička HTTP Public Key Pinning byla z hodnocení odstraněna, Chrome ji od verze 72 nepodporuje a odstranit ji plánuje i Firefox 72. Sloužila k tomu, aby browser přijal odpověď serveru jen tehdy, když přijde s certifikátem, jehož veřejný klíč odpovídá tomu, co má browser zapamatováno. Bránilo to vystavování falešných certifikátů pro vaši doménu, například hacknutím certifikační autority. Ale bylo to dost problematické, museli jste si dávat pozor ještě větší než na HTTP Strict Transport Security. Když jste si totiž pořídili certifikát třeba od jiné autority a zapomněli použít nebo ztratili původní klíč, tak se na web nedalo dostat, nikdo se na něj nepřipojil. Museli jste také mít zálohy klíčů, nejlépe i jednu na papíře. Já to raději nebudu více rozebírat, nebo si stihnete ještě před finálním odstraněním rozbít weby a budete to svádět na mě. HPKP mělo i report-only variantu v podobě hlavičky Public-Key-Pins-Report-Only, ale i ta byla odstraněna. Reporty si můžete posílat na již známou službu report-uri.com.

X-XSS-Protection: 0, X-XSS-Protection: 1; mode=block

#13 Hlavička X-XSS-Protection ovládá tzv. XSS auditor (někdy nazývaný XSS filtr) v Chrome, IE a Edge. Ve verzi 78 byl z Chromia (a tím pádem i Chrome a Edge) zcela odstraněn. Auditor detekoval útoky typu Reflected Cross-Site Scripting (XSS) a zablokuje jeho spuštění. Byl standardně zapnutý a nastavený do režimu „zobraz stránku“, ale tento režim byste neměli používat. XSS filtry mohou mít chyby a někdy mohou pokusem o vyčištění stránky naopak nějaký XSS útok vyrobit. Zároveň je možné takto část nějakého důležitého JavaScriptu vyřadit z provozu. Zkuste si to na https://exploited.cz/xss/. Použijte raději některé z hlaviček výše. Hodnota 0 XSS filtr zcela vypíná, to se hodí pro případy, kdy ve stránce máte nějaký důležitý JavaScript, který je potřeba vždy za každých okolností spustit. Pro ty ostatní je tu ta druhá hlavička s mode=block, ta zařídí, že když auditor detekuje Reflected XSS, tak se stránka pro jistotu vůbec nezobrazí.

Just kicked Stack Overflow's Google Analytics over to https:// because some mobile carriers were rerouting to to inject ads. Thanks, jerks.

#14 Nejen ty správné HTTP hlavičky umí v tu správnou chvíli zablokovat nebezpečný obsah. Diskuzní server Stack Overflow musel začít načítat kód Google Analytics z HTTPS, aby ho poskytovatelé připojení nemohli měnit a vkládat tak do stránek reklamy. Takoví mizerní poskytovatelé by sice mohli hacknout servery Google a změnit kód přímo tam, ale to je velmi nepravděpodobné. Pokud ale ve stránkách používáte nějaké jiné JavaScripty třetích stran nebo je vkládáte z nějakých CDN, tak by se mohlo stát, že je někdo opravdu změní „přímo u zdroje“.

Subresource Integrity (SRI) <script src="…" integrity="sha256-…" crossorigin="anonymous">

#15 Takovým změnám má právě zabránit Subresource Integrity (SRI). Základem je nový atribut integrity pro značky script a link, který obsahuje hash dat. Pokud uvedený hash odpovídá hashi dat, která se pomocí té značky stáhla do browseru, tak se „pustí“ dále, aby je browser zpracoval. Když se hashe liší, prohlížeč data zahodí. Používat SRI nemá moc smysl, když vkládané soubory a HTML, do kterého se vkládají jsou na stejném místě, ale ničemu to neškodí. SRI musí být podorováno i na straně serveru, ten musí podporovat Cross-Origin Resource Sharing (CORS), více viz dále. jQuery CDN takovou věc podporuje a doporučuje, GitHub také.

SHA-2: sha256, sha384, sha512

#16 SRI hash může být jakýkoliv hash z rodiny SHA-2, tedy SHA-256, SHA-384, SHA-512. V atributu integrity může být hashů více, pokud jsou všechny stejného typu, např. sha256, tak prohlížeč hash příchozích dat porovná se všemi hashi v atributu, dokud nenajde shodu. Pokud jsou různého typu, například sha256 a sha512 v jednom atributu, tak prohlížeč použije ten silnější hash, v tomto případě sha512. Hash není uveden v hexadecimálním tvaru, ale je to binární reprezentace zakódovaná do Base64. Správný hash a formát vám pomůže vyrobit třeba SRI Hash Generator, z lokálního souboru ho pak spočítáte pomocí openssl: cat soubor.js | openssl dgst -sha256 -binary | openssl enc -base64.

crossorigin="anonymous", Origin: https://www.foo, Access-Control-Allow-Origin: https://www.foo

#17 Již jsem zmiňoval, že pro správnou funkčnost SRI je potřeba používat Cross-Origin Resource Sharing (CORS). V podstatě to znamená, že browser s požadavkem musí poslat hlavičku Origin s aktuální doménou, což zařídí právě atribut crossorigin. Jeho hodnota anonymous znamená, že se s požadavkem nepošlou cookies. Cílový server musí odpovědět hlavičkou Access-Control-Allow-Origin, jejíž hodnotou bude buď obsah hlavičky Origin, nebo *. Pokud chcete SRI používat v Nette a Latte, tak sledujte vývoj balíčku spaze/sri-macros.

A+ lednička

#18 Když může známku A+ dostat lednička, tak můžete i vy!

Video záznam

YouTube

Michal Špaček

Michal Špaček

Vyvíjím webové aplikace, zajímá mě jejich bezpečnost. Nebojím se o tom mluvit veřejně, hledám hranice tak, že je posouvám. Chci naučit webové vývojáře stavět bezpečnější a výkonnější weby a aplikace.

Veřejná školení

Zvu vás na následující školení, která pořádám a vedu: