Bezpečný sandboxovaný iframe

V HTML5 můžeme pomocí atributu sandbox vkládat na obsah iframe rozličná bezpečnostní omezení. Pojďme se podívat, jaká to jsou a jak je můžeme používat.
Nálepky:
Tento text je zkráceným překladem článku Play safely in sandboxed IFrames, jehož autorem je Mike West a je zde zveřejněn pod licencí CC-BY-3.0.
Na dnešním webu se často nedokážeme úplně vyhnout vkládání komponent, nad kterými nemáme žádnou kontrolu. Widgety od třetích stran mohou hrát pro UX důležitou roli. A každý takový vložený widget je možným místem útoku.
Princip nejnižších privilegií
Hodil by se nám mechanismus, který by vloženému obsahu přidělil minimální oprávnění, která ještě postačí k tomu, aby mohl správně fungovat. Pokud widget nevyžaduje vyskakovací okna, nebude mu vadit, když mu odepřeme přístup k window.open, pokud nepotřebuje Flash, nevznikne žádný problém, když mu vypneme podporu pluginů apod. Následujeme tím tzv. princip nejnižších privilegií.
Tím prvním krokem správným směrem je použití iframe. To zajistí oddělení obsahu vkládaného z nedůvěryhodného zdroje od naší aplikace. Obsah z iframe se nedostane k DOMu naší stránky ani k datům, která máme uložena lokálně, ani nemůže kreslit na libovolnou pozici ve stránce, je omezen na prostor rámce. Oddělení samo o sobě není ovšem dostatečné. Obsah v iframe má stále mnoho možností, jak uživatele obtěžovat nebo zmást: automaticky spuštěné video, pluginy a vyskakovací okna jsou jen špičkou ledovce.
Tady nám pomůže atributsandbox prvku iframe , který umí oprávnění rámce omezit. Můžeme tak prohlížeči říct, aby nahrál do daného rámce obsah a přidělil mu jen omezenou sadu privilegií.
Takovým dobrým příkladem je tlačítko „Tweetni“, to můžeme vložit pomocí iframe tímto kódem:
<iframe src="https://platform.twitter.com/widgets/tweet_button.html"
style="border: 0; width:130px; height:20px;"></iframe>
Tlačítko potřebuje přístup k JavaScriptu ze serverů Twitteru a k vyskakovacím oknům. Dále pak ke cookies, aby mohlo tweet přiřadit účtu přihlášeného uživatele, a konečně potřebuje odesílat formuláře, aby mohl uživatel napsaný tweet odeslat. To by mohlo stačit.
Sandboxování konfigurujeme pomocí whitelistu, v našem případě postačí:
<iframe sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
src="https://platform.twitter.com/widgets/tweet_button.html"
style="border: 0; width:130px; height:20px;"></iframe>
Přehled privilegií
Pokud iframu přidělíme prázdný atribut sandbox ( <iframe sandbox src="...">), bude rámec maximálně sandboxovaný, tj.:
</iframe>
- JavaScript se v rámci nespustí, to se nevztahuje pouze na JavaScript vložený značkou
script, ale také na všechny inline handlery a URL typujavascript:. Bude se zobrazovat obsah ve značcenoscript, přesně tak, jako kdyby skriptování zakázal sám uživatel. - Dokument v rámci bude nahrán pod samostatný origin, tzn. nebude mít žádný přístup k datům vázaným na doménu, tj. cookies ani webová úložistě (DOM storage, Indexed DB apod.).
- Dokument nemůže vytvářet nová okna a dialogy (např. pomocí
window.opennebotarget="_blank"). - Formuláře nebude možné odeslat.
- Pluginy nebudou nahrány.
- Dokument může navigovat pouze obsah sebe sama, zavolání
window.top.locationvyvolá výjimku a kliknutí na odkaz ztarget="_top"nebude mít žádný efekt. - Automaticky spouštěné vlastnosti jsou zakázány (autofokus formulářových prvků, automatické spouštění videa apod.).
- Dokument nemůže uzamknout ukazatel myši.
- U prvků
iframev embedovaném dokumentu bude ignorován atributseamless.
Všechna tato omezení můžeme zrušit, kromě omezení pluginů, ty v sandboxovaných rámcích nepůjdou spustit nikdy:
allow-formspovolí odesílání formulářůallow-popupspovolí vyskakovací oknaallow-pointer-lockpovolí uzamčení ukazatele myšiallow-same-originpovolí dokumentu zachovat jeho origin, tj. dokument zhttps://example.com/bude mít přístup k datům z této doményallow-scriptspovolí spouštění JavaScriptu a současně povolí automaticky spouštěné vlastnosti (protože by bylo triviální je implementovat JavaScriptem)allow-top-navigationpovolí dokumentu navigaci top-level okna
Připomeňme si, že našemu tweetovacímu tlačítku jsem povolili:
allow-scriptsallow-popupsallow-formsallow-same-origin
Pozn.: Nesmíme zapomenout zmínit, že sandboxování iframe se vztahuje i na všechna okna a rámce, které tento iframe vytvoří. V našem případě jsme museli přidat allow-forms , i přestože odesílací formulář je umístěn ve vyskakovacím okně.
Demo
Sandboxování si můžete vyzkoušet v jednoduchém demu Evalbox, stačí do něj vložit javascriptový kód a můžete porovnat jeho výsledek spuštěný v obyčejném a v sandboxovaném iframe.
Podpora prohlížečů
Sandboxování dnes podporuje řada prohlížečů: Firefox 17+, IE10+ a Chrome (viz caniuse).
Další čtení
- Privilege Separation in HTML5 Applications
- Sandboxování může být flexibilnější pomocí dvou atributů
srcdocaseamless. První z nich nám umožní vložit do rámce obsah, aniž bychom musely vytvářet další HTTP požadavek, ten druhý zařídí, aby se kaskádové styly dokumentu vztahovaly i na obsah viframe. Oba mají jen minimální podporu v prohlížečích (noční buildy Chrome a WebKitu), ale do budoucna se jedná o zajímavou kombinaci, se kterou bude možné sandboxovat například komentáře uživatelů:<iframe sandbox seamless srcdoc="<p>Toto je komentář uživatele! Nemůže spustit žádný skript! To se @spazef0rze nebude ale vůbec líbit 8-)</p>"></iframe>
O této možnosti jsem slyšel poprvé, díky.
Myslim, ze nasledujici dve odrazky si odporuji:
Pokud iframu přidělíme prázdný atribut sandbox ……..
– JavaScript se v rámci nespustí, to se nevztahuje pouze na JavaScript vložený značkou script, ale také na všechny inline handlery a URL typu javascript:. Bude se zobrazovat obsah ve značce noscript, přesně tak, jako kdyby skriptování zakázal sám uživatel.
…
– Dokument může navigovat pouze obsah sebe sama, zavolání window.top.location vyvolá výjimku. (Vsadim obe boty, ze nevyvola :))
Postřeh dobrý, úvaha špatná. Zavolání window.top.location výjimku rozhodně vyvolá, nicméně k onomu zavolání vůbec nedojde. A podobně to platí i pro 2., 3. a 8., které rovněž používají JavaScript.
Mno, a vzhledem k tomu, ze k zavolani nedojde, ani zadna vyjimka vyvolana byt nemuze, ne?
No to je ovšem už jiné tvrzení.
A co ak, is to iframe zmenim, pripadne uplne vymazem atributu sandbox cez firebug resp. aj v chrome a inde a poziadavku odoslem nasledovne, podobne ako ked sa ladia javascriptove veci za pochodu pri testovani? Je toto nejak osetrene v prehliadacoch? Moc sa v tom neorientujem, tak dakujem za vysvetlenie.
To projde jako jakákoliv jiná změna. Nechápu, proč by to mělo být nějak zvlášť ošetření. Není, být nemůže a není důvod, proč by mělo být.
Mozem sa spytat ake je realne pouzitie v praxi, pripadne nejaky web, ktory to pouziva? Neorientujem sa v tom preto ma to zaujima. Dakujem.
Nezkoumal jsem zda to některý ze známých webů už nasadil, není důvod proč ne, v zásadě na většinu dnešních použití iframe se sandbox hodí, minimálně zakázání top-navigation. Pokud vás stále použití nenapadá, počkejte až se sandbox víc rozšíří a bude to jasnější.