Zabezpečení webu: prevence XSS, CSRF a SQL injection

Bezpečnost webu: Prevence XSS, CSRF, SQL Injection

Proč zabezpečení webu selhává a jak tomu předejít

Webové aplikace jsou složité systémy, které zpracovávají neustálý tok neověřených vstupů: parametry URL, těla požadavků, cookies, hlavičky a události v prohlížeči. Tři z historicky nejkritičtějších tříd zranitelností jsou XSS (Cross-Site Scripting), CSRF (Cross-Site Request Forgery) a SQL Injection. Tyto chyby vyplývají z chybné práce s důvěrou: důvěry v data od uživatele, v prohlížeč, v databázi a v síť. Tento článek shrnuje hrozby, kořenové příčiny a praktické, na frameworku nezávislé postupy obrany.

Model hrozeb a kořenové příčiny

  • Nedostatečná validace a kontextové kódování: vstupy se bez úprav míchají s kódem (HTML, JS, SQL).
  • Zneužitelný stav relace: chybí ochrana proti podvržení nebo odcizení relace (tokeny CSRF, SameSite, rotace identifikátorů).
  • Chybná separace oprávnění: aplikace vykonává příkazy v databázi s nadměrnými oprávněními, klientský kód důvěřuje nedůvěryhodným datům.
  • Slabá pozorovatelnost: chybí detekce anomálií, korelace logů a upozornění na podezřelé sekvence požadavků.

Cross-Site Scripting (XSS): typy a scénáře

  • Reflected XSS: škodlivý vstup se vrací v odpovědi (např. parametr q při vyhledávání) a spustí se v prohlížeči oběti.
  • Stored XSS: payload se uloží do databáze (komentáře, profily) a spustí se při každém zobrazení.
  • DOM-based XSS: manipulace s DOM na straně klienta (např. location.hash, document.write) bez účasti serveru.

XSS: dopady a útočné vektory

Útočník může číst nebo zapisovat data v kontextu domény oběti, krást cookies (pokud nejsou HttpOnly), provádět akce jménem uživatele, upravovat obsah stránky nebo vkládat phishingový obsah. Významná rizika nastávají u aplikací SPA s rozsáhlým využitím JavaScriptu, kde se s DOM manipuluje častěji a ve větším rozsahu.

Obrana proti XSS: vícevrstvá strategie

  • Kontextové kódování (escaping): při výstupu do textu HTML kódujte &<>"'; v atributu HTML navíc hlídejte uvozovky a nebezpečné protokoly; v řetězci JavaScriptu escapujte speciální znaky; v parametrech URL používejte percent-encoding.
  • Šablonovací systémy s automatickým escapováním: upřednostňujte enginy a frameworky s funkcí auto-escaping (např. výchozí šablonovací systémy na straně serveru, React/Angular na straně klienta). Pokud potřebujete použít výstup „raw“, bezpečně jej filtrujte pomocí whitelistu.
  • Content Security Policy (CSP): nasazujte pravidla bez unsafe-inline; upřednostňujte přístup založený na nonce (script-src 'nonce-…') a oddělení skriptů do externích souborů. U rozsáhlejších aplikací SPA zvažte Trusted Types, které vynucují používání bezpečných API při přiřazování do DOM.
  • HttpOnly a Secure pro cookies: zabrání čtení relace skriptem; kombinujte s SameSite pro zmírnění rizika CSRF.
  • Sanitizace HTML: pokud musíte zobrazovat uživatelský obsah HTML, používejte knihovny s whitelistem značek a atributů, které zakazují obslužné rutiny událostí a nebezpečná schémata URL.
  • Zakázané konstrukce: omezte používání eval, new Function, document.write a dynamických přiřazení do innerHTML; upřednostňujte bezpečná API (textContent, setAttribute s validací).

CSRF (Cross-Site Request Forgery): princip a příznaky

CSRF zneužívá skutečnost, že prohlížeč automaticky přikládá cookies k požadavkům na danou doménu. Útočník podstrčí oběti požadavek (formulář, obrázek, skript, CORS) tak, aby aplikace provedla akci, kterou oběť nechtěla (změna e-mailu, hesla, převod peněz). CSRF cílí na stav – operace, které jej mění (POST/PUT/PATCH/DELETE) bez dostatečného ověření záměru uživatele.

CSRF: obranné techniky

  • Antiforgery tokeny: kryptograficky náhodné, vázané na relaci, jednorázové nebo rotované; ověřujte je u každého požadavku, který mění stav.
  • Atribut SameSite u cookies: SameSite=Lax jako rozumné výchozí nastavení; pro citlivé akce a tradiční weby lze použít Strict (pozor na uživatelský komfort); v kombinaci s Secure a HttpOnly.
  • Ověření původu: u požadavků měnících stav kontrolujte hlavičky Origin a Referer; prázdné nebo cizí originy odmítejte.
  • Oddělení idempotentních a stav měnících operací: GET musí být bez vedlejších efektů; akce vyžadují POST s tokenem a případně opětovné ověření totožnosti.
  • Vyhněte se autentizaci API založené pouze na cookies: pro veřejná API upřednostňujte tokeny bearer v hlavičce Authorization (automaticky se nepřikládají napříč originy).
  • Nespoléhejte na CORS: CORS řeší sdílení zdrojů mezi originy, nikoli CSRF – nebrání automatickému přikládání cookies u jednoduchých požadavků.

SQL Injection: kořenový problém a varianty

  • Klasická (error/union-based): manipulace s dotazem přímou injekcí vkládaných řetězců.
  • Blind (boolean/time-based): odvozování informací podle odezvy, i když se chyby nezobrazují.
  • Second-order: škodlivý vstup se uloží a později se znovu použije v jiném dotazu.

SQL Injection: obranné vzory

  • Parametrizované dotazy: používejte prepared statements s vázanými parametry; nikdy neskládejte řetězec SQL konkatenací uživatelských vstupů.
  • ORM/Query builder: používejte bezpečná API a vyhýbejte se „raw SQL“ bez řádné parametrizace.
  • Princip nejnižších oprávnění: aplikační účet v databázi má mít minimální oprávnění (bez DROP/ALTER, pouze nezbytná SELECT/INSERT/UPDATE/DELETE).
  • Vstupy ověřované pomocí whitelistu: číselné identifikátory převádějte na integer, výčtové hodnoty ověřujte vůči seznamu; text nikdy nezapojujte do struktury dotazu (např. do názvů sloupců).
  • Oddělení povinností: různé funkční oblasti a dávkové úlohy používají samostatné účty v databázi.
  • Bezpečné logování: logy nesmějí obsahovat celé dotazy s citlivými daty; maskujte hodnoty a dbejte na GDPR.

Bezpečné zpracování vstupů: od validace k normalizaci

  • Kanonikalizace: před validací převádějte vstup do kanonického tvaru (normalizace Unicode, odstranění nulových bajtů, sjednocení konců řádků).
  • Validace před obchodní logikou: co nejdříve odmítněte neplatné vstupy a vracejte přesné, ale bezpečné chybové zprávy (bez úniku informací o struktuře systému).
  • Oddělení dat a kódu: vstupní data nikdy nesmějí měnit programovou logiku ani kontext instrukcí.

Bezpečná relace a správa cookies

  • Rotace ID relace: po přihlášení i při zvýšení oprávnění.
  • Časové limity: idle timeout a absolute timeout, opětovné ověření totožnosti u kritických akcí.
  • Příznaky: HttpOnly, Secure, SameSite; zákaz ukládání relace do URL.

Bezpečnostní hlavičky a konfigurace serveru

  • CSP (viz výše), X-Content-Type-Options: nosniff, Referrer-Policy, Permissions-Policy, Strict-Transport-Security pro vynucení HTTPS.
  • Oddělení statického obsahu a aplikace: reverzní proxy, omezení přístupu k administračnímu rozhraní, omezení počtu požadavků a ochrana proti útokům hrubou silou.

Testování: SAST, DAST, IAST a fuzzing

  • SAST: statická analýza kódu v CI, pravidla pro nebezpečná API a konstrukce šablon.
  • DAST: dynamické skenery testující běžící aplikaci, integrované do QA pipeline a využívající autentizaci.
  • IAST/RASP: senzory v aplikaci pro přesnější detekci skutečných problémů během testování.
  • Fuzzing: generování neočekávaných vstupů a sekvencí požadavků s monitorováním chyb a anomálií.

Bezpečný SDLC a řízení bezpečnosti

  • Bezpečnostní požadavky: definujte nefunkční požadavky (CSP, tokeny, parametrizace) již při návrhu.
  • Kontrola kódu pomocí bezpečnostních kontrolních seznamů: povinné schvalování změn se zaměřením na kontext výstupu, práci s databází a relací.
  • Závislosti: skenování knihoven (SCA), zásady správy verzí, SBOM a rychlá reakce na CVE.
  • Reakce na incidenty: provozní postupy, detekce anomálií XSS/SQLi, blokování a postupy pro rychlé opravy, následná analýza incidentu a získané poznatky.

Monitorování a detekce útoků

  • Aplikační logy: korelace neobvyklých parametrů, chybových kódů, dlouhých dotazů a jejich časování.
  • WAF/ochrana za běhu: signatury typických payloadů (např. <script>, UNION SELECT), vždy však pouze jako doplněk ke skutečným nápravám v kódu.
  • Telemetrie databáze: upozornění na sleep()/časové anomálie, neobvykle vysoký počet chybových dotazů a eskalaci oprávnění.

Specifika SPA, API a mikrofrontendů

  • SPA: důsledně používejte bezpečné vazby, CSP s nonce a Trusted Types; spravujte stav bez serializace nedůvěryhodných dat do innerHTML.
  • API: oddělené domény, autentizace v hlavičkách (bearer), CORS s explicitními seznamy povolených originů; žádné zpětné vkládání vstupů do chybových zpráv bez kódování.
  • Mikrofrontendy: sandboxované prvky <iframe> s atributy sandbox/allow; přísná CSP a postMessage s ověřováním originu.

Praktické anti-patterny a jak je odstranit

  • Skládání řetězců HTML/JS: nahraďte jej komponentovým nebo šablonovacím enginem s automatickým escapováním.
  • „Globální“ uživatel databáze: vytvořte role s minimálními oprávněními pro jednotlivé služby.
  • Ochrana CSRF jen u některých formulářů: opatřete tokenem všechny akce měnící stav, včetně požadavků AJAX.
  • Logování celých SQL dotazů a cookies: údaje maskujte a anonymizujte, dodržujte zásady ochrany soukromí.

Kontrolní seznam: XSS, CSRF, SQLi v praxi

  • XSS: automatické escapování, CSP bez unsafe-inline, Trusted Types (pokud je to možné), zákaz eval, cookies HttpOnly.
  • CSRF: antiforgery token, cookies SameSite a Secure, kontrola Origin/Referer, pro změny používejte pouze POST.
  • SQLi: parametrizované dotazy, whitelist typů, omezená oprávnění databáze, žádné skládání SQL z řetězců.
  • Testování: SAST/DAST v CI, skenování závislostí, pravidelné penetrační testy a modelování hrozeb.

Závěr: bezpečnost jako inženýrská disciplína

Ochrana proti XSS, CSRF a SQL Injection není jednorázový úkol, ale nepřetržitý proces, který začíná návrhem, pokračuje implementací bezpečných konstrukcí a průběžným testováním a završuje jej provozní pozorovatelnost a připravenost na incidenty. Úspěch spočívá v důsledném oddělení dat od kódu, v kontextově správném kódování, v kryptograficky silné obraně proti podvržení požadavků a v disciplinovaném přístupu k databázím. Investice do bezpečného SDLC snižuje rizika, posiluje důvěru uživatelů a z dlouhodobého hlediska zkracuje dobu potřebnou k dodávání změn.