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.
Hlavičky
- X-Frame-Options
- Content-Security-Policy
- Strict-Transport-Security
- X-Content-Type-Options
- Public-Key-Pins
- X-XSS-Protection
Subresource Integrity (SRI)
1. Michal ŠpačekMichal Špaček www.michalspacek.czwww.michalspacek.cz @spazef0rze@spazef0rze
XFO XCTO XXP SRI
OMG WTF BBQ
Překlad: HTTP hlavičky, Subresource Integrity a spol.
Přednáška o všech těchto zkratkách, za kterými se skrývají bezpečnostní HTTP
hlavičky a atributy. Původní slajdy tyto poznámky neobsahují.
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 securityheaders.io si otestujte váš web, jak moc a
které bezpečnostní hlavičky používá.
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.
5. http://exploited.cz/frames/
Vyzkoušejte si to: podívejte se na výsledky ankety o běhání, zapamatujte si stav
poslední 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.
6. X-Frame-Options: SAMEORIGIN
X-Frame-Options: DENY
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.
7. Content Security Policy:
frame-ancestors 'none'
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.
8. Content-Security-Policy
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.
9. Content-Security-Policy-Report-Only:
default-src https:; report-uri …
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.io.
10. Strict-Transport-Security:
max-age=31536000; includeSubDomains;
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.
11. X-Content-Type-Options: nosniff
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 http://exploited.cz/content/ a sledujte konzoli browseru.
12. HTTP Public Key Pinning (HPKP)
Public-Key-Pins
HTTP Public Key Pinning slouží 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ání to vystavování falešných certifikátů pro vaši doménu,
například hacknutím certifikační autority. Ale na tohle si dávejte pozor ještě větší než
na HTTP Strict Transport Security, protože když si pak pořídíte certifikát třeba od jiné
autority, zapomenete použít nebo ztratíte původní klíč, tak si web zcela
znefunkčníte, nikdo se na něj nepřipojí. Musíte také mít zálohy klíčů, nejlépe i jednu
na papíře. Já to raději nebudu více rozebírat, nebo si rozbijete weby a budete to
svádět na mě. HPKP má také report-only variantu v podobě hlavičky Public-Key-
Pins-Report-Only, tu používejte minimálně do doby, dokud neprojdete procesem
obnovy certifikátu. Reporty si můžete posílat na již známou službu report-uri.io.
13. X-XSS-Protection: 0
X-XSS-Protection: 1; mode=block
Hlavička X-XSS-Protection ovládá tzv. XSS auditor (někdy nazývaný XSS filtr) v
Chrome, IE a Edge. Auditor detekuje útoky typu Reflected Cross-Site Scripting
(XSS) a zablokuje jeho spuštění. Je 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 http://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í.
14. https://twitter.com/Nick_Craver/status/684456928953679872
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“.
15. Subresource Integrity
<script src="…"
integrity="sha256-…"
crossorigin="anonymous">
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é.
16. SHA-2
sha256
sha384
sha512
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
17. crossorigin="anonymous"
Origin: https://www.foo
Access-Control-Allow-Origin: https://www.foo
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.