Autor: .cCuMiNn. | 14.3.2011 |
Zranitelnost Cross Site Scripting je opravdu všudypřítomná. V průměru se odhaduje, že tímto typem zranitelnosti trpí asi 80% všech webových aplikací. Některé z nich jsou přitom tak rozsáhlé, že vyhledat v nich všechna slabá místa, která útočníkům umožňují spuštění kódu, může být téměř nereálné. Navíc vám nikdo nezaručí, že i když se Vám podaří všechny tyto bezpečnostní trhliny zacelit, neobjeví se někdy v budoucnu nový způsob, který injektáž skriptu umožní.
Správně napsaná a zabezpečená aplikace je určitě základním stavebním kamenem v celé bezpečnostní politice. Je ale zřejmé, že je zapotřebí i nějaký účinný nástroj, který by v této nelehké situaci vypomohl.
Když se zamyslíme nad tím, co to vlastně XSS je a co jej způsobuje, dojdeme k závěru, že webový browser nedokáže rozpoznat rozdíl mezi legitimním skriptem umístěným v HTML dokumentu a skriptem, který je injektován útočníkem.
Toho si samozřejmě všimli i vývojáři webových prohlížečů a doplňků pro ně. Snažili se proto vzít neutěšenou situaci s XSS do vlastních rukou, aby koncové uživatele před jejími dopady ochránili. Vnikly tak nástroje, kterými jsou například NoScript (doplněk pro FireFox) nebo XSS Filter implementovaný v Internet Exploreru od jeho osmé verze.
Tyto nástroje se snaží odhalit pokus o injektáž non-persistentních skriptů, když porovnávají obsah požadavků odesílaných webovým prohlížečem a odpověď, která je vrácena serverem. Pokud se v odpovědi vyskytuje nebezpečný kód, který byl obsažen i v samotném požadavku, je pravděpodobné, že došlo k pokusu o útok a injektovaný skript je různými metodami deaktivován.
Tento způsob je sice v některých případech skutečně účinný. Nedokáže ovšem podchytit všechny možné varianty útoku a pro zkušeného útočníka tak většinou není problém tyto kontrolní mechanismy obejít.
Už před mnoha lety se proto někteří lidé začali zabývat otázkou rozlišovaní původu vkládaného obsahu, aby webový prohlížeč nemusel tápat ve tmě a dokázal rozlišit, zda je vložený obsah legitimní nebo ne. Díky takovým autoritám, jako jsou Rsnake, Gerv nebo Jeremiah Grossman, vnikl nakonec koncept nového nástroje v boji proti XSS, kterým je bezpečnostní politika Content Security Policy.
Použití Content Security Policy umožňuje vývojářům webových aplikací jasně definovat zdroje dat importovaných do obsahu webové stánky a zabránit tak injektáži jakéhokoliv jiného obsahu. Aby mohl být tento nástroj v boji proti Cross Site Scriptingu skutečně účinný, zavádí následující defaultní omezení.
- Jsou zakázány veškeré skripty umístěné tagem <script> přímo do obsahu HTML dokumentu. <script>alert(1)</script>
+ Povoleno je naopak načítání scriptů z externích souborů. Jejich konkrétní umístění přitom ale musí být tvůrcem aplikace explicitně povoleno pomocí CSP.
- Je zakázáno použití pseudoprotokolu javascript: URIs <a href="javascript:bad_stuff()">
- Je zakázáno definování ovladačů událostí přímo u jednotlivých prvků HTML <a onclick="bad_stuff()">
+ Povoleno je pro ošetření událostí definování jejich posluchačů addEventListener("click", function(), false);
- Jsou zakázány funkce eval(), setTimeout() a setInterval() s přímo obsaženým kódem setTimeout("evil string...", 1000)
+ Funkce setTimeout a setInterval mohou ale spouštět funkce setTimeout(myFunc, 1000)
- Je zakázáno použití kontrusktoru new function var f = new Function("evil string...")
+ Funkce mohou být deklarovány pomocí fukčních operátorů function f() { some_code } nebo var f = function() { some_code }
- Je zakázáno použití data: URIs jako zdroje dat pro jiné než povolené prvky <img src="data:image/jpg,...">
- Je zakázáno použití XBL bindings pro jiné protokoly než chrome: nebo resource: např. -moz-bindings pro navázání CSS stylů
Podpora CSP musí být implementována jednak ve webových prohlížečích, ale i v samotné webové aplikaci. Aplikace totiž musí webovému prohlížeči explicitně říci, že předávaný dokument je chráněn restrikcemi CSP. Tuto informaci může aplikace browseru předat dvěmi způsoby. HTTP hlavičkou
X-Content-Security-Policy:
nebo v případě Report only módu, o kterém si povíme níže, HTTP hlavičkou
X-Content-Security-Policy-Report-Only
Nemáme-li k dispozici možnost odesílat HTTP hlavičky přímo, můžete využít druhé možnosti, která spočívá v předávání infromace o použití CSP prostřednictvím <meta> tagu, který musí být prvním prvkem tohoto typu v hlavičce dokumentu.
<meta http-equiv="X-Content-Security-Policy">
<meta http-equiv="X-Content-Security-Policy-Report-Only">
V případě použití obou uvedených variant, má HTTP hlavička přednost před tagem <meta>
POZOR! V konečné implementaci CSP do Firefoxu 4 nebyla možnost definování politiky pomocí prvků <meta> z bezpečnostních důvodů umožněna. V současné době je tedy možné pravidla CSP předávat pouze HTTP hlavičkou. Uvidíme, zda bude podpora pro <meta> tagy zavedena někdy v budoucnosti.
U jednotlivých direktiv se pak vždy zapisuje seznam zdrojů, ze kterých je možné data pro dané prvky načítat. Přitom formát zapisovaných zdrojů je následující:
Povolení načítání jakéhokoliv zdroje ze stejného hostitele jako pochází samotný chráněný dokument, zajistíte následující hlavičkou:
X-Content-Security-Policy: default-src 'self'
Povolení načítání jakéhokoliv zdroje (kromě blíže specifikovaných) ze stejného hostitele, obrázky odkudkoliv, objekty z domén media1.com nebo media2.com a skripty pouze z hosta userscripts.example.com zajistíte následující hlavičkou:
X-Content-Security-Policy: default-src 'self'; img-src *; object-src media1.com media2.com; script-src userscripts.example.com
POZOR! direktiva default-src byla původně pojmenována allow a v této podobě je implementována také ve Firefoxu 4. Nevím, jakým směrem se bude tato direktiva ubírat v budoucnosti, ale v současné době není podporována. Je nutné použít direktivu allow.
V případě, že jsou bezpečnostní pravidla načítaná z externího souboru využitím direktivy policy-uri, pak tento musí pocházet ze stejné domény a musí být předáván jako MIME typ Content-Type text/x-content-security-policy
Kromě samotného blokování zdrojů, které nepochází ze zdrojů definovaných v bezpečnostní politice, může být správce webové aplikace také informován o pokusu o narušení integrity HTML dokumentu zaslíním reportu. Stačí k tomu, aby byla v politice použita direktiva report-uri, která definuje jednu nebo více lokací, na kterou budou tyto reporty prohlížečem odeslány. Reporty jsou odesílány HTTP metodou POST jako JSON objekt s Content-type application/json a mohou být odesílány pouze v rámci stejného hosta, ze kterého pochází chráněný dokument. Browser navíc nesmí následovat přesměrování 3xx při odesílání reportu.
Z uvedených informací je patrné, že CSP skutečně dokáže zabránit jekémukoliv propašování skriptů do obsahu HTML dokumnetu a to jak v perzistentní, tak i v non-perzistentní podobě. Při vhodně nasazeném CSP je injektáž skriptů řádově těžší, protože by útočník musel nejprve získat kontrolu nad seznamem povolených zdrojů.
V současné době je Content Security Policy podporováno zatím jen ve Firefoxu 4. Určitě se ale jedná o krok správným směrem, který by dokázal jednou provždy vymýtit z webu zneužívání XSS. Věřím proto, že brzy dojde k jeho standardizaci a širšímu rozšíření.
Doporučuji vám, abyste na tuto bezpečnostní politiku mysleli při tvorbě webových aplikací již nyní. Budete-li se totiž řídit principy, na kterých je postavena, vyhnete se tím pozdějšímu přepisování aplikace do správné podoby. Nic vám navíc nebrání ani v tom, abyste ve své aplikaci zavedli plnou podporu CSP. Webové prohlížeče, které CSP nepodporují, budou uvedené hlavičky jednoduše ignorovat. Uživatelé, kteří začnou používat Firefox 4 vám navíc mohou pomocí reportů o narušení pomoci s nalezením slabě zabezpečených chyb. Můžete je pak lépe ošetřet pro ty uživatele, kteří používají webové browsery bez podpory CSP.
Pro bliží informace doporučuji navštívit webovou stránku obsahující specifikaci CSP: https://dvcs.w3.org/hg/content-security-policy/raw-file/bcf1c45f312f/csp-unofficial-draft-20110303.html