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
SameSitepro 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.writea dynamických přiřazení doinnerHTML; upřednostňujte bezpečná API (textContent,setAttributes 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=Laxjako rozumné výchozí nastavení; pro citlivé akce a tradiční weby lze použítStrict(pozor na uživatelský komfort); v kombinaci sSecureaHttpOnly. - Ověření původu: u požadavků měnících stav kontrolujte hlavičky
OriginaReferer; 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 atributysandbox/allow; přísná CSP apostMessages 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ákazeval, cookies HttpOnly. - CSRF: antiforgery token, cookies
SameSiteaSecure, kontrolaOrigin/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.
