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ěra 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é, rámcově 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: absence ochrany proti podvržení nebo odcizení session (CSRF tokeny, SameSite, rotace identifikátorů).
- Chybná separace kompetencí: 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 alerting pro podezřelé sekvence požadavků.
Cross-Site Scripting (XSS): typy a scénáře
- Reflected XSS: škodlivý vstup je vrácen v odpovědi (např. parametr q v hledání), vykoná se v prohlížeči oběti.
- Stored XSS: payload uložen v databázi (komentáře, profily) a vykonává se při každém zobrazení.
- DOM-based XSS: manipulace s DOM na klientu (např.
location.hash,document.write) bez serverového podílu.
XSS: dopady a útokové vektory
Útočník může číst/psát 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, injektovat phishing. Významná rizika nastávají u SPA aplikací s bohatým JS, kde DOM manipulace probíhají častěji a v širším rozsahu.
Obrana proti XSS: vícevrstvá strategie
- Kontextové kódování (escaping): při výstupu do HTML textu kódujte
&<>"'; v HTML atributu navíc hlídejte uzávorky a nebezpečné protokoly; v JavaScript stringu escapujte speciální znaky; v URL parametrech používejte percent-encoding. - Šablonovací systémy s automatickým escape: preferujte enginy a frameworky, které mají auto-escaping (např. výchozí šablonovače na straně serveru, React/Angular na klientu). Při vědomé potřebě „raw“ výstupu proveďte bezpečné filtrování whitelistem.
- Content Security Policy (CSP): nasazujte pravidla bez
unsafe-inline; preferujte nonce-based přístup (script-src 'nonce-…') a oddělení skriptů do externích souborů. U větších SPA zvažte Trusted Types pro vynucení bezpečných API při přiřazování do DOM. - HttpOnly a Secure pro cookies: zamezí čtení session skriptem; kombinujte s
SameSitepro mitigaci CSRF. - Sanitizace HTML: pokud musíte zobrazit uživatelský HTML obsah, používejte knihovny s whitelistem značek/atributů a zákazem event handlerů a nebezpečných URL schémat.
- Zakázané konstrukce: omezte
eval,new Function,document.write, dynamickáinnerHTMLpřiřazení; preferujte bezpečné API (textContent,setAttributes validací).
CSRF (Cross-Site Request Forgery): princip a symptomy
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 vykonala akci, kterou oběť nechtěla (změna emailu, hesla, převod peněz). CSRF cílí na stavy – měnící operace (POST/PUT/PATCH/DELETE) bez dostatečné verifikace záměru uživatele.
CSRF: obranné techniky
- Antiforgery tokeny: kryptograficky náhodné, vázané na relaci, jednorázové nebo rotované; validovat v každém měnícím požadavku.
- SameSite atribut u cookies:
SameSite=Laxjako rozumný výchozí stav; pro citlivé akce a tradiční weby možnéStrict(pozor na UX); v kombinaci sSecureaHttpOnly. - Validace původu: kontrola hlaviček
OriginaRefereru state-changing požadavků; odmítnout prázdné nebo cizí originy. - Oddělení idempotentních a měnících operací: GET musí být bez vedlejších efektů; akce vyžadují POST s tokenem a případně re-autentizaci.
- Vyvarovat se „cookie-only“ autentizace pro API: preferujte bearer tokeny v
Authorizationhlavičce pro veřejná API (nepřikládají se automaticky napříč originy). - Nespoléhat na CORS: CORS řeší sdílení zdrojů mezi originy, nikoli CSRF – nechrání před automatickým přikládáním cookies u jednoduchých požadavků.
SQL Injection: kořenový problém a varianty
- Klasická (error/union-based): manipulace dotazu přímou injekcí vkládaných řetězců.
- Blind (boolean/time-based): inference podle odezvy, i když se chyby nesdělují.
- Second-order: škodlivý vstup uložen, později znovu použit v jiném dotazu.
SQL Injection: obranné patterny
- Parametrizované dotazy: používejte prepared statements s bind parametry; nikdy neskládejte SQL string pomocí konkatenace uživatelských vstupů.
- ORM/Query builder: respektujte bezpečná API, vyhýbejte se „raw SQL“ bez řádného parametrizování.
- Least privilege: aplikační DB účet má minimální práva (bez
DROP/ALTER, pouze nutnéSELECT/INSERT/UPDATE/DELETE). - Whitelisting vstupů: číselné identifikátory převádějte na integer, enumerace validujte proti seznamu; text nikdy nepromítejte do struktury dotazu (např. názvy sloupců).
- Oddělení povinností: různé funkční oblasti a batch úlohy používají samostatné DB účty.
- Bezpečné logování: logy nesmí obsahovat celé dotazy s citlivými daty; maskujte hodnoty a dbejte na GDPR.
Bezpečné zpracování vstupů: od validace k normalizaci
- Canonicalization: před validací převést vstup do kanonického tvaru (normalizace Unicode, odstranění nulových bytů, sjednocení konců řádků).
- Validace před byznysem: odmítnout nevalidní vstupy co nejdříve, vracet přesné, ale bezpečné chyby (bez leaků o struktuře systému).
- Separace dat a kódu: vstupní data nikdy nesmějí měnit programovou logiku nebo instrukční kontext.
Bezpečná relace a správa cookies
- Rotace session ID: po přihlášení i při navýšení oprávnění.
- Časová omezení: idle timeout a absolute timeout, re-autentizace u kritických akcí.
- Flagy:
HttpOnly,Secure,SameSite; zákaz ukládání session 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í statiky a aplikace: reverzní proxy, omezení expozice admin rozhraní, rate-limiting a ochrana proti brute-force.
Testování: SAST, DAST, IAST a fuzzing
- SAST: statická analýza kódu v CI, pravidla pro nebezpečné API a šablonové konstrukce.
- DAST: dynamické skenery proti běžící aplikaci, integrované do QA pipeline s autentizací.
- IAST/RASP: senzory v aplikaci pro přesnější detekci skutečných problémů během testů.
- Fuzzing: generování nečekaných vstupů a sekvencí požadavků s monitoringem chyb a anomálií.
Bezpečný SDLC a governance
- Bezpečnostní požadavky: definujte nefunkční požadavky (CSP, tokeny, parametrizace) hned při návrhu.
- Code review s bezpečnostními checklisty: povinné schvalování změn s focus na kontext výstupu, práci s DB a relací.
- Závislosti: skenování knihoven (SCA), politiky verzí, SBOM a rychlá reakce na CVE.
- Incident response: runbooky, detekce XSS/SQLi anomálií, blokace a hotfix postupy, post-mortem a lessons learned.
Monitoring a detekce útoků
- Aplikační logy: korelace neobvyklých parametrů, chybových kódů, dlouhých dotazů a časování.
- WAF/Runtime ochrany: signatury pro typické payloady (např.
<script>,UNION SELECT), ale vždy jako doplněk k opravdovým nápravám v kódu. - Telemetrie DB: výstrahy na
sleep()/časové anomálie, nezvyklé množství chybových dotazů, eskalace práv.
Specifika SPA, API a mikrofrontendů
- SPA: důsledné používání bezpečných bindingů, CSP s nonce, Trusted Types; správa stavu bez serializace nedůvěryhodných dat do
innerHTML. - API: oddělené domény, autentizace v hlavičkách (bearer), CORS s explicitními allowlisty; žádné reflexe vstupů do chybových zpráv bez kódování.
- Mikrofrontendy: sandboxované
<iframe>s atributysandbox/allow; přísná CSP apostMessages validací originu.
Praktické anti-patterny a jak je odstranit
- Skládání HTML/JS stringů: nahraďte komponentovým/šablonovým enginem s auto-escapingem.
- „Global“ DB uživatel: vytvořte role s minimálními právy pro jednotlivé služby.
- CSRF ochrana jen na některých formulářích: tokenizujte všechny změnové akce, včetně AJAX.
- Logování celých SQL a cookies: maskujte a anonymizujte, dodržujte zásady soukromí.
Checklist: XSS, CSRF, SQLi v praxi
- XSS: auto-escaping, CSP bez
unsafe-inline, Trusted Types (pokud lze), zákazeval, HttpOnly cookies. - CSRF: antiforgery token,
SameSiteaSecurecookies, kontrolaOrigin/Referer, jen POST pro změny. - SQLi: parametrizované dotazy, whitelist typů, omezená DB práva, žádné stringové skládání SQL.
- Testing: SAST/DAST v CI, dependency scanning, pravidelné pen-testy a threat modeling.
Závěr: bezpečnost jako inženýrská disciplína
Ochrana proti XSS, CSRF a SQL Injection není jednorázový úkol, ale kontinuální proces, který začíná návrhem, pokračuje implementací bezpečných konstrukcí, průběžným testováním a končí provozní observabilitou a připraveností na incidenty. Úspěch spočívá v přísné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, zlepšuje důvěru uživatelů a dlouhodobě zkracuje dobu potřebnou k dodání změn.