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 ve vyhledávání), vykoná se v prohlížeči oběti.
- Stored XSS: payload uložený v databázi (komentáře, profily) a vykonávající se při každém zobrazení.
- DOM-based XSS: manipulace s DOM na klientovi (např.
location.hash,document.write) bez serverového podílu.
XSS: dopady a útokové vektory
Útočník může číst a 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 injektovat phishingové útoky. Významná rizika nastávají u SPA aplikací s bohatým JavaScriptem, kde manipulace s DOM 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 atributech navíc kontrolujte uzávorky a nebezpečné protokoly; v JavaScriptových řetězcích 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í pomocí whitelistu.
- Content Security Policy (CSP): nasazujte pravidla bez
unsafe-inline; preferujte přístup založený na nonce (script-src 'nonce-…') a oddělení skriptů do externích souborů. U větších SPA zvažte použití Trusted Types pro vynucení bezpečných API při přiřazování do DOM. - HttpOnly a Secure pro cookies: zamezí čtení session skripty; kombinujte s
SameSitepro mitigaci CSRF. - Sanitizace HTML: pokud je nutné zobrazovat uživatelský HTML obsah, používejte knihovny s whitelistem značek a atributů a bez event handlerů či nebezpečných URL schémat.
- Zakázané konstrukce: omezte používání
eval,new Function,document.writea dynamických přiřazení doinnerHTML; 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), aby aplikace vykonala akci, kterou oběť nechtěla (změna e-mailu, hesla, převod peněz). CSRF cílí na stavy – operace měnící stav (POST/PUT/PATCH/DELETE) bez dostatečné verifikace uživatelova záměru.
CSRF: obranné techniky
- Antiforgery tokeny: kryptograficky náhodné, vázané na relaci, jednorázové nebo rotované; validujte je u každého měnícího požadavku.
- SameSite atribut u cookies:
SameSite=Laxje rozumný výchozí stav; pro citlivé akce a tradiční weby lze použítStrict(pozor na uživatelskou zkušenost); kombinujte 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ů; změny vyžadují POST s tokenem a případně opětovnou autentizaci.
- Vyvarovat se „cookie-only“ autentizace pro API: preferujte bearer tokeny v
Authorizationhlavičce pro veřejná API (tyto tokeny se nepřikládají 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 na základě odezvy, i když se chyby nesdělují.
- Second-order: škodlivý vstup uložený a 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 řetězce pomocí konkatenace uživatelských vstupů.
- ORM/Query builder: využívejte bezpečná API, vyhýbejte se „raw SQL“ bez správné parametrizace.
- Princip nejmenších oprávnění: aplikační databázový účet má minimální práva (bez
DROPčiALTER, pouze nezbytnáSELECT,INSERT,UPDATE,DELETE). - Whitelisting vstupů: číselné identifikátory převádějte na integer, enumerace validujte proti seznamu; textové vstupy nikdy nepoužívejte přímo ve struktuře dotazu (např. názvy sloupců).
- Oddělení povinností: různé funkční oblasti a batch úlohy používejte samostatné databázové účty.
- Bezpečné logování: logy nesmí obsahovat celé dotazy s citlivými daty; maskujte hodnoty a dbejte na dodržování GDPR.
Bezpečné zpracování vstupů: od validace k normalizaci
- Kanonizace: před validací převádějte vstupy do kanonického tvaru (normalizace Unicode, odstranění nulových bytů, sjednocení konců řádků).
- Validace před byznysem: odmítněte nevalidní vstupy co nejdříve, vracejte přesné, ale bezpečné chyby (bez úniku informací 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 zvyšování oprávnění.
- Časová omezení: idle timeout a absolute timeout, opětovná 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 útokům.
Testování: SAST, DAST, IAST a fuzzing
- SAST: statická analýza kódu v CI systému, 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 testování.
- 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) již při návrhu.
- Code review s bezpečnostními checklisty: povinné schvalování změn s důrazem na kontext výstupu, práci s databází 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()a č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 tokeny), CORS s explicitními allowlisty; žádné reflektování vstupů do chybových zpráv bez kódování.
- Mikrofrontendy: sandboxované
<iframe>s atributysandboxaallow; přísná CSP apostMessages validací originu.
Praktické anti-patterny a jak je odstranit
- Skládání HTML/JS řetězců: nahraďte komponentovým či šablonovým enginem s auto-escapingem.
- „Globalní“ databázový 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 měnící akce, včetně AJAX požadavků.
- Logování celých SQL dotazů a cookies: maskujte a anonymizujte, dodržujte zásady ochrany soukromí.
Checklist: XSS, CSRF, SQLi v praxi
- XSS: auto-escaping, CSP bez
unsafe-inline, Trusted Types (pokud možné), zákazeval, HttpOnly cookies. - CSRF: antiforgery token,
SameSiteaSecurecookies, kontrolaOriginaReferer, změny pouze přes POST. - SQLi: parametrizované dotazy, whitelist typů, omezená databázová práva, žádné skládání SQL řetězců.
- Testování: SAST/DAST v CI, skenování závislostí, pravidelné penetrační 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.