Chýba Content-Security-Policy
Čo to je
Vaše stránky neposielajú hlavičku Content-Security-Policy. Táto hlavička prehliadaču hovorí, z akých zdrojov smie načítať skripty, obrázky, fonty a iframy.
Bez nej prehliadač spustí akýkoľvek kód, ktorý sa v HTML objaví — či už ho tam dal váš tím, alebo útočník cez XSS.
Prečo je to problém
CSP je jediná účinná obrana proti cross-site scripting (XSS). Keď útočník niekde v aplikácii objaví dieru, cez ktorú pretlačí <script>, bez CSP mu prehliadač ten script s radosťou spustí. S CSP mu prehliadač povie „tento zdroj nemám v allowliste“ a script padne.
Druhá rovina — ochrana pred injektovanými drainermi a SEO spamom. Ak máte správne nastavený script-src, útočník cez hacknutý plugin nemôže ľahko pridať externý script.
Ako to opraviť
CSP je politika, ktorá môže rozbiť stránku. Nasaďte ju najskôr v report-only režime.
Fáza 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-reportTáto politika nič neblokuje — len pošle JSON na /csp-report pri každom porušení. Sledujte logy niekoľko dní, aby ste vedeli, aké skripty/obrázky/fonty stránka skutočne používa.
Fáza 2 — vyladiť allowlist
Z reportov zostavte konkrétny allowlist. Príklad pre 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áza 3 — prepnúť na enforce
Keď report-only nehlási žiadne legitímne porušenie, zmeňte hlavičku z Content-Security-Policy-Report-Only na Content-Security-Policy.
Pozor na 'unsafe-inline'
Inline skripty (<script>...</script>) aj inline event handlery (onclick="...") vyžadujú 'unsafe-inline'. Tým ale CSP príde o väčšinu hodnoty proti XSS. Lepšie je použiť nonce alebo hash a inline skripty postupne vyhodiť. WordPress má pre nonce vstavanú podporu.
Konkrétne implementácie
- nginx:
add_header Content-Security-Policy "..." always; - Apache:
Header always set Content-Security-Policy "..." - WordPress plugin: HTTP Headers