Chybí Content-Security-Policy

Co to je

Vaše stránky neposílají hlavičku Content-Security-Policy. Tahle hlavička prohlížeči říká, z jakých zdrojů smí načíst skripty, obrázky, fonty, iframy.

Bez ní prohlížeč spustí jakýkoliv kód, který se v HTML objeví — ať už ho tam dal váš tým, nebo útočník přes XSS.

Proč je to problém

CSP je jediná efektivní obrana proti cross-site scripting (XSS). Když útočník někde v aplikaci objeví díru, kterou tam protlačí <script>, bez CSP mu prohlížeč ten script s radostí spustí. S CSP mu prohlížeč řekne „tenhle zdroj nemám v allowlistu“ a script padne.

Druhá rovina — ochrana před injektovanými drainery a SEO spamem. Pokud máte správně nastavené script-src, útočník přes hacknutý plugin nemůže snadno přidat externí script.

Jak to opravit

CSP je politika, která může rozbít stránku. Nasaďte ji nejdříve v report-only režimu.

Fáze 1 — report-only

Content-Security-Policy-Report-Only: default-src 'self'; img-src 'self' data: https:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; report-uri /csp-report

Tahle politika nic neblokuje — jen pošle JSON na /csp-report při každém porušení. Sledujte logy několik dnů, abyste věděli, jaké skripty/obrázky/fonty stránka skutečně používá.

Fáze 2 — vyladit allowlist

Z reportů sestavte konkrétní allowlist. Příklad pro WordPress s Google Fonts a analytikou Umami:

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://i.xhs.cz;
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
  font-src 'self' https://fonts.gstatic.com;
  img-src 'self' data: https://*.gravatar.com;
  connect-src 'self' https://i.xhs.cz;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';

Fáze 3 — přepnout na enforce

Až report-only nehlásí žádné legitimní porušení, změňte hlavičku z Content-Security-Policy-Report-Only na Content-Security-Policy.

Pozor na 'unsafe-inline'

Inline skripty (<script>...</script>) i inline event handlery (onclick="...") vyžadují 'unsafe-inline'. Tím ale CSP přijde o většinu hodnoty proti XSS. Lepší je použít nonce nebo hash a inline skripty postupně vyhodit. WordPress má pro nonce vestavěnou podporu.

Konkrétní implementace

Reference