Zpět na blog

Security headers: HSTS, CSP, X-Frame-Options a další

· 7 min čtení

Backend je pevnost, ale druhá polovina obrany je v prohlížeči. HSTS, CSP a další hlavičky blokují XSS, clickjacking i MITM - a jsou zdarma.

Security headers: HSTS, CSP, X-Frame-Options a další

Proč na nich záleží

Aplikace může být na backendu dokonale bezpečná, a přesto být zranitelná vůči útokům na straně prohlížeče: cross-site scripting (XSS), clickjacking, protocol downgrade, MIME confusion. Security headery posouvají obranu přímo do prohlížeče.

Strict-Transport-Security (HSTS)

Vynutí HTTPS pro všechny budoucí návštěvy. Po první návštěvě přes HTTPS si prohlížeč doménu zapamatuje a sám přepíše jakýkoli http:// odkaz na https://, i když uživatel klikne na špatný odkaz.

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
  • max-age=63072000 = platí 2 roky
  • includeSubDomains = pravidlo platí i pro všechny subdomény; vynutí HTTPS všude, takže pokud máte subdoménu běžící jen přes HTTP, např. staging.example.com, stane se v prohlížeči nedostupnou
  • preload = umožňuje zařazení do HSTS preload listu, který je zabudován v Chrome / Firefox / Safari

Pozor: Odstranění HSTS s preload ze seznamu trvá 6+ měsíců. Nezahrnujte preload dřív, než si ověříte, že HTTPS funguje stabilně i na všech subdoménách.

Content-Security-Policy (CSP)

Nejmocnější, ale zároveň nejhůř nastavitelná hlavička. Whitelistuje, odkud smí prohlížeč načítat skripty, styly, obrázky a iframy. Bez CSP může útočník, který dokáže injectnout <script> tag, spustit libovolný JS; s CSP jen kód ze schválených zdrojů.

Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-...'; img-src 'self' data: https://cdn.example.com; style-src 'self' 'unsafe-inline'; frame-ancestors 'none'

Běžné direktivy:

  • default-src 'self' = ve výchozím stavu povol jen zdroje z mé domény
  • script-src = JS zdroje (pro inline skripty uveďte hash nebo nonce)
  • style-src = CSS zdroje
  • img-src = obrázky
  • connect-src = AJAX, WebSocket, EventSource
  • frame-ancestors 'none' = nikdo nesmí stránku embednout do iframe (lepší než X-Frame-Options)
  • report-uri /csp-report = prohlížeč pošle JSON při každé violation (vy ji zachytíte v backendu a zalogujete)
  • Poznámka: report-uri je dnes deprecated - prohlížeče s podporou report-to ho ignorují. Moderní způsob je direktiva report-to plus samostatná hlavička Reporting-Endpoints; report-uri ponechte jen jako fallback pro Firefox, který report-to zatím nepodporuje.

X-Frame-Options

Starší alternativa k frame-ancestors. Brání clickjackingu, kdy útočník vloží vaši stránku jako iframe a překryje ji neviditelnými tlačítky.

X-Frame-Options: DENY

Hodnoty: DENY (nikdo), SAMEORIGIN (jen moje doména), ALLOW-FROM uri (deprecated).

X-Content-Type-Options

X-Content-Type-Options: nosniff

Vypne MIME sniffing, takže prohlížeč respektuje Content-Type, který vrátil server. Bez toho může útočník nahrát soubor se špatným typem (např. obrázek, který je ve skutečnosti HTML se skriptem) a prohlížeč ho může spustit jako webovou stránku.

Referrer-Policy

Referrer-Policy: strict-origin-when-cross-origin

Řídí, kolik informací o předchozí stránce pošle prohlížeč v hlavičce Referer při kliknutí. Výchozí hodnota v moderních prohlížečích už je strict-origin-when-cross-origin, ale explicitní nastavení hlavičky zaručí konzistentní chování.

Permissions-Policy

Vypne API, která nepotřebujete, jako kameru, mikrofon, GPS a geolokaci. Útočník zneužívající XSS o tato API nemůže požádat.

Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()

Praktická konfigurace v nginx

server {
  listen 443 ssl http2;
  server_name example.com;

  add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;
  # preload jsme zde záměrně vynechali - přidej ho až když si jsi 100% jistý (viz past s preload výše)
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-Frame-Options "DENY" always;
  add_header Referrer-Policy "strict-origin-when-cross-origin" always;
  add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;

  # CSP je rozsáhlá - definujte ji podle své aplikace
  add_header Content-Security-Policy "default-src 'self'; script-src 'self'; ..." always;
}

Klíčové je always - bez něj nginx hlavičky u error response (4xx, 5xx) vynechá.

Audit aktuálního stavu

Nejjednodušší je online nástroj. Náš header check vám ukáže, které hlavičky chybí a které jsou nesprávné. Pro důkladný audit dá securityheaders.com i skóre A-F.

Závěr

Security headery patří mezi nejlepší investice v bezpečnosti z pohledu poměru úsilí a zisku: typicky půlhodina nastavení v reverse proxy proti celé kategorii útoků na straně prohlížeče. Audit jednou za půl roku v rámci pravidelné údržby je rozumné minimum.

Bezplatný audit security headers

Bez registrace, výsledek do tří sekund.

Otestovat web →

Sdílet: Odkaz zkopírován

Vyzkoušejte ePulz.io zdarma - 7 dní bez kreditní karty.

Vytvořit účet