Backend/Server

XSS

Co je to XSS?

XSS neboli Cross-Site Scripting je jedna z nejrozšířenějších bezpečnostních zranitelností webových aplikací, která umožňuje útočníkovi vložit škodlivý JavaScript kód do webové stránky, jenž se následně provede v prohlížeči ostatních uživatelů. Představte si, že navštívíte důvěryhodný web, který jste navštěvovali už stokrát – ale tentokrát je v něm skrytý nebezpečný kód, který ukradne vaše přihlašovací údaje nebo vás přesměruje na falešnou stránku. Přesně tak funguje XSS útok. Název "Cross-Site Scripting" označuje skutečnost, že útočník dokáže spustit svůj skript v kontextu jiného webu – odtud "cross-site". XSS zranitelnost vzniká, když web nedostatečně ošetřuje uživatelský vstup – například text z kontaktního formuláře, vyhledávací dotaz, URL parametr nebo komentář pod článkem. Pokud vývojář takový vstup rovnou vypíše na stránku bez escapování HTML entit, útočník může místo běžného textu vložit JavaScript kód, který se spustí u všech návštěvníků. XSS útoky jsou podle OWASP Top 10 (žebříček nejkritičtějších bezpečnostních rizik) dlouhodobě mezi nejčastějšími hrozbami webových aplikací. Důsledky můžou být vážné – od krádeže session cookies a přihlašovacích údajů přes phishing až po kompletní převzetí uživatelského účtu. Pro majitele webu to znamená ztrátu důvěry zákazníků, možné právní důsledky kvůli úniku osobních dat a poškození reputace.

Jak XSS útoky fungují v praxi?

Mechanismus XSS útoku je relativně přímočarý, ale jeho dopady mohou být devastující. Útočník najde místo na webu, kde může vložit svůj vstup – typicky formulářové pole, URL parametr nebo jakékoliv místo, kde web přijímá data od uživatelů. Místo legitimního vstupu (například jména "Jan Novák") vloží JavaScript kód zabalený v HTML tagu, například <script>alert('XSS')</script>. Pokud web tento vstup nedostatečně validuje a následně ho vypíše na stránku, prohlížeč tento kód vykoná jako legitimní součást stránky.

Skutečné útoky jsou sofistikovanější než jednoduchý alert box. Útočník může ukrást session cookie pomocí document.cookie a odeslat ji na svůj server. S touto cookie se pak může vydávat za oběť a získat přístup k jejímu účtu bez znalosti hesla. Může také modifikovat DOM stránky a vytvořit falešný přihlašovací formulář, který vypadá identicky jako originál – uživatel zadá své údaje a útočník je zachytí. Další možností je přesměrování na phishingovou stránku nebo stažení malwaru. Klíčové je, že tento škodlivý kód běží s oprávněními původní stránky – má přístup ke stejným cookies, session storage a může provádět AJAX požadavky do API webu. Z pohledu prohlížeče je to legitimní kód webu, nikoli útok.

Typy XSS útoků

  • Reflected XSS (Odražený útok)

  • Reflected XSS je nejčastější typ, kdy škodlivý kód je součástí URL nebo požadavku a okamžitě se "odrazí" zpět uživateli ve výsledné stránce. Útočník vytvoří speciální odkaz obsahující XSS payload (například https://web.cz/search?q=<script>...</script>) a rozešle ho obětím emailem nebo sociálními sítěmi. Když oběť na odkaz klikne, web zobrazí výsledky vyhledávání včetně nešetřeného škodlivého kódu. Reflected XSS není uložen v databázi, takže každý útok vyžaduje, aby oběť klikla na připravený odkaz. Obrana zahrnuje validaci všech GET/POST parametrů a escapování výstupu.

  • Stored XSS (Uložený útok)

  • Stored XSS je nejnebezpečnější varianta, protože škodlivý kód se trvale uloží do databáze webu. Typické scénáře zahrnují komentáře pod články, uživatelské profily, fóra nebo recenze produktů. Útočník vloží XSS payload do komentáře, který se uloží do databáze. Následně se tento komentář zobrazí všem návštěvníkům dané stránky a škodlivý kód se automaticky vykoná u každého z nich. Stored XSS nevyžaduje, aby oběť klikla na specifický odkaz – stačí navštívit napadenou stránku. Jeden útok tak může postihnout tisíce uživatelů. Obrana vyžaduje sanitizaci všech dat před uložením do databáze a escapování při vypisování.

  • DOM-based XSS (Útok na DOM)

  • DOM-based XSS je specifický typ, kdy se útok odehrává kompletně na straně klienta bez zapojení serveru. JavaScript kód webu čte data z nebezpečného zdroje (například URL hash, location.search nebo localStorage) a vkládá je přímo do DOM pomocí innerHTML, eval() nebo podobných funkcí bez ošetření. Server nikdy nevidí škodlivý payload, takže server-side validace nepomůže. Příklad: web čte parametr z URL pomocí document.location.hash a vloží ho do stránky přes element.innerHTML = hash. Útočník vytvoří URL s payloadem v hash části a kód se vykoná. Obrana spočívá v bezpečné práci s DOM – používání textContent místo innerHTML, validace všech dat z nedůvěryhodných zdrojů a vyhýbání se eval().

Jak se bránit XSS útokům?

Ochrana proti XSS vyžaduje kombinaci několika bezpečnostních vrstev. Základním pravidlem je: nikdy nevěřte uživatelskému vstupu. Každý vstup od uživatele – ať už z formuláře, URL parametru, cookies nebo dokonce HTTP hlaviček – považujte za potenciálně nebezpečný, dokud ho neověříte a neošetříte.

  • Validace a sanitizace vstupu

  • První linie obrany je validace vstupu – ověřte, že data odpovídají očekávanému formátu. Pokud očekáváte email, zkontrolujte, že vstup je validní emailová adresa. Pokud očekáváte číslo, ověřte, že vstup obsahuje pouze číslice. Whitelist přístup (povolit pouze známé bezpečné znaky) je bezpečnější než blacklist (zakázat nebezpečné znaky), protože útočníci neustále hledají nové způsoby obfuskace. Sanitizace vstupu znamená odstranění nebo neutralizaci nebezpečných znaků – například odstranění HTML tagů pomocí funkce strip_tags() v PHP nebo bezpečnostní knihovny jako HTML Purifier. Pozor však – sanitizace sama o sobě nestačí, protože existuje nekonečně způsobů, jak obejít filtry.

  • Output encoding (Escapování výstupu)

  • Nejdůležitější ochrana proti XSS je escapování výstupu – tedy převod speciálních HTML znaků na jejich entity při vypisování dat na stránku. V PHP používejte funkci htmlspecialchars($data, ENT_QUOTES, 'UTF-8'), která převede znaky jako <, >, & a uvozovky na HTML entity (&lt;, &gt;, atd.). Prohlížeč pak tyto entity zobrazí jako text, nikoli jako executable kód. Moderní frameworky jako React, Vue nebo Angular mají automatické escapování zabudované – když použijete {'{'}variable{'}'} v JSX, framework automaticky escapuje obsah. Důležité je escapovat data podle kontextu – jinak se escapuje HTML obsah, jinak HTML atributy, jinak JavaScript stringy a jinak CSS.

  • Content Security Policy (CSP)

  • Content Security Policy je HTTP hlavička, která definuje, ze kterých zdrojů může prohlížeč načítat skripty, styly, obrázky a další zdroje. CSP výrazně ztěžuje exploitaci XSS zranitelnosti. Například CSP hlavička Content-Security-Policy: script-src 'self' povolí JavaScriptu načítat se pouze ze stejné domény jako web – inline skripty a externí zdroje budou zablokovány. I když útočník dokáže vložit XSS payload, prohlížeč ho odmítne vykonat kvůli CSP. CSP je defense-in-depth vrstva – nezabraňuje vzniku XSS zranitelnosti, ale výrazně omezuje škodu, kterou může útočník způsobit. Nasazení CSP vyžaduje důkladné testování, protože špatně nakonfigurovaná politika může rozbít legitimní funkcionalitu webu.

  • HTTPOnly a Secure cookies

  • Nastavte session cookies s atributem HttpOnly, který zabraňuje JavaScriptu přístup k cookies pomocí document.cookie. I když útočník uspěje s XSS útokem, nemůže ukrást session cookie. V PHP nastavíte HttpOnly cookie takto: setcookie('session', $value, ['httponly' => true, 'secure' => true, 'samesite' => 'Strict']). Atribut Secure zajistí, že cookie se posílá pouze přes HTTPS, a SameSite chrání před CSRF útoky.

XSS v různých technologiích

Každá technologie má své specifické nástroje a best practices pro prevenci XSS. V PHP vždy používejte htmlspecialchars() nebo htmlentities() pro výstup do HTML. Pro složitější HTML (například blog s formátováním) použijte knihovnu HTML Purifier, která povolí bezpečné tagy jako <b>, <i>, ale odfiltruje nebezpečný kód. V JavaScriptu se vyhněte použití innerHTML s nedůvěryhodnými daty – místo toho používejte textContent nebo innerText, které vkládají data jako text, ne jako HTML. Funkce eval(), setTimeout() a setInterval() s string argumenty jsou také nebezpečné. WordPress má vestavěné funkce pro escapování: esc_html() pro HTML obsah, esc_attr() pro HTML atributy, esc_url() pro URL a esc_js() pro JavaScript. Nikdy nevypisujte uživatelská data bez použití těchto funkcí. Moderní JavaScript frameworky jako React automaticky escapují obsah vložený přes JSX – <div>{'{'}userInput{'}'}</div> je bezpečné. Pozor však na dangerouslySetInnerHTML v Reactu, který obchází ochranu a měl by se používat pouze s důvěryhodnými daty.

Nejčastější chyby vedoucí k XSS

  • Důvěra v client-side validaci

  • Důvěra v client-side validaci je kritická chyba – JavaScript validace v prohlížeči je snadno obejitelná. Útočník může vypnout JavaScript, upravit DOM pomocí DevTools nebo poslat požadavek přímo pomocí cURL. Validace musí vždy probíhat na serveru.

  • Neošetřené URL parametry a vyhledávací dotazy

  • Neošetřené URL parametry a vyhledávací dotazy jsou častou vstupní branou pro Reflected XSS. Vývojáři často vypíšou vyhledávací dotaz zpět uživateli ("Výsledky pro: [dotaz]") bez escapování.

  • Používání blacklistu místo whitelistu

  • Snaha blokovat nebezpečné znaky (<, >, script) vede k nekonečnému boji s novými obfuskačními technikami. Útočníci používají HTML entity, Unicode, různá kódování a case-mixing (ScRiPt) pro obejití filtrů. Whitelist přístup (povolit pouze písmena, číslice a vybrané znaky) je mnohem bezpečnější.

  • Zapomenuté escapování v šablonách

  • Moderní template enginy často automaticky escapují, ale vývojář může tuto ochranu vypnout (například {{ '{{'}variable|raw{{'}}'}} v Twig). Takové místo musí být pečlivě ošetřeno.

  • Nedostatečné CSP

  • CSP s script-src 'unsafe-inline' neochraňuje proti XSS, protože povoluje inline skripty.

Nejčastější otázky o XSS

Co je XSS útoky jednoduše vysvětleno? Rozbalit

XSS (Cross-Site Scripting) je typ bezpečnostní zranitelnosti, kdy útočník dokáže vložit škodlivý JavaScript kód do webové stránky. Tento kód se pak provede v prohlížeči ostatních uživatelů, kteří stránku navštíví. Útočník tak může ukrást přihlašovací údaje, odeslat uživatele na falešnou stránku nebo provádět akce jménem oběti. XSS vzniká, když web správně neošetří uživatelský vstup – například text z formuláře nebo URL parametr.

Jaké jsou typy XSS útoků? Rozbalit

Existují tři hlavní typy XSS útoků: 1) Reflected XSS – škodlivý kód je součástí URL a provede se okamžitě po kliknutí. 2) Stored XSS – nebezpečný kód se uloží do databáze (např. komentář) a provádí se u každého, kdo zobrazí danou stránku. 3) DOM-based XSS – útok probíhá čistě na straně prohlížeče manipulací s DOM bez zapojení serveru. Stored XSS je nejnebezpečnější, protože postihuje všechny návštěvníky automaticky.

Jak se bránit XSS útokům? Rozbalit

Ochrana proti XSS zahrnuje několik klíčových kroků: 1) Validace a sanitizace vstupu – ověřujte všechny uživatelské vstupy a odstraňujte nebezpečné znaky. 2) Output encoding – při vypisování dat escapujte HTML entity pomocí funkcí jako htmlspecialchars() v PHP. 3) Content Security Policy (CSP) – HTTP hlavička omezující zdroje skriptů. 4) HTTPOnly cookies – zabraňuje JavaScriptu přístup k cookies. 5) Používejte bezpečnostní frameworky, které automaticky ošetřují vstup. Moderní frameworky jako React nebo Vue mají vestavěnou ochranu.

Je můj WordPress web zranitelný vůči XSS? Rozbalit

WordPress sám o sobě má vestavěné funkce pro prevenci XSS (wp_kses, esc_html, esc_attr), ale zranitelnost často přichází s pluginy a tématy od třetích stran. Zastaralé pluginy jsou častou příčinou XSS útoků. Ochraňte se pravidelným aktualizováním WordPressu, pluginů a témat, používáním pouze ověřených pluginů z oficiálního repozitáře a instalací bezpečnostních pluginů jako Wordfence nebo Sucuri.

Související pojmy