Kort sagt: Security headers er anvisninger fra webserveren til browseren, som beskytter besøgende mod angreb som cross-site scripting, clickjacking og ukrypterede forbindelser. De vigtigste er HSTS, Content Security Policy, X-Content-Type-Options, beskyttelse mod fremmede rammer, Referrer-Policy og Permissions-Policy. De er en fornuftig hærdning, men erstatter ikke opdateringer på serveren.
Hvad security headers kan, og hvad ikke
Ved hvert sidekald sender webserveren ud over indholdet også headere med. Nogle af dem styrer browserens sikkerhedsfunktioner. Dermed kan man f.eks. fastlægge, at en side kun indlæses via HTTPS, eller at browseren ikke udfører scripts fra fremmede domæner.
For driftsansvarlige er indplaceringen vigtig: Headere beskytter først og fremmest de besøgende, f.eks. mod opsnapning af sessioner eller manipulerede formularer. De lukker ingen sårbarheder på serveren. En svaghed i PHP, i CMS'et eller i en udvidelse består, uanset hvor godt headerne er sat. I samspil med ren kode begrænser de dog følgerne af mange fejl tydeligt.
De vigtigste security headers i overblik
| Header | Formål | Anbefaling som udgangspunkt |
|---|---|---|
| Strict-Transport-Security (HSTS) | gennemtvinger HTTPS ved fremtidige kald | max-age=31536000; includeSubDomains |
| Content-Security-Policy (CSP) | fastlægger tilladte kilder til scripts, billeder, rammer | individuelt, først som Report-Only |
| X-Content-Type-Options | forhindrer, at browseren gætter filtyper | nosniff |
| X-Frame-Options henholdsvis CSP frame-ancestors | forhindrer indlejring på fremmede sider (clickjacking) | SAMEORIGIN henholdsvis frame-ancestors 'self' |
| Referrer-Policy | begrænser, hvilken adresse der videregives til andre sider | strict-origin-when-cross-origin |
| Permissions-Policy | slår browserfunktioner som kamera eller placering fra | tillad kun nødvendige funktioner |
HSTS bør I først sætte, når alle underdomæner pålideligt kan nås via HTTPS. Browseren husker anvisningen i den angivne tid; en fejl kan så ikke tages tilbage med det samme. Begynd eventuelt med en kort varighed, og forøg den efter vellykkede tests. Den ekstra mulighed preload indtaster domænet varigt i browserproducenternes lister og bør kun sættes efter omhyggelig kontrol.
Headere er desuden ikke det eneste sted, hvor browseren yder beskyttelse. Cookies bør bære attributterne Secure, HttpOnly og SameSite, så sessioner ikke opsnappes via ukrypterede forbindelser eller scripts. Hvordan I indstiller det i PHP, beskriver vejledningen om sessioner.
Sæt security headers i Nginx
I Nginx hører headerne hjemme i server-blokken for det pågældende website. Tilføjelsen always sørger for, at de også sendes ved fejlsider.
server {
# ...
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'" always;
server_tokens off;
}
En ejendommelighed ved Nginx: Sætter en location-blok egne add_header-anvisninger, bliver headerne fra server-blokken ikke overtaget dér. Kontrollér derfor også undersider og statiske filer. Yderligere hærdning til denne kombination beskriver Sikr Nginx med PHP-FPM.
Sæt security headers i Apache
Under Apache har I brug for modulet mod_headers. Anvisningerne hører hjemme i VirtualHost eller, hvis der ikke er adgang til den, i .htaccess.
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
Header always set Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
</IfModule>
ServerTokens Prod
ServerSignature Off
ServerTokens og ServerSignature hører hjemme i hovedkonfigurationen. De forhindrer, at serveren nævner sin præcise version i svar og fejlsider. I php.ini opnår I det samme for PHP med expose_php = Off.
Indfør Content Security Policy trinvis
Content Security Policy er den mest virksomme, men også mest krævende header. Den fastlægger, fra hvilke kilder scripts, stylesheets, billeder, skrifttyper og rammer må indlæses. Bliver et indsmuglet script hentet fra et fremmed domæne, blokerer browseren det.
Moderne websites indbinder ofte analyseværktøjer, betalingsudbydere, kortservices eller videoer. En for streng politik lammer så funktioner. Gå derfor frem i trin:
- Start først med
Content-Security-Policy-Report-Only. Browseren melder overtrædelser i udviklerkonsollen eller til en samleadresse, men blokerer intet. - Registrér alle nødvendige kilder, og frigiv dem målrettet i stedet for at bruge generelle jokertegn.
- Flyt inline-scripts trinvis ud i filer, eller forsyn dem med nonces, så
'unsafe-inline'kan undværes. - Skift først efter en testfase uden uventede meddelelser over til
Content-Security-Policy.
CSP'en supplerer ren escaping i koden, men erstatter den ikke. Hvordan I sikrer output i PHP rigtigt, står i vejledningen Forhindr cross-site scripting i PHP.
Kontrollér headere og undgå typiske fejl
Efter hver ændring bør I kontrollere, om headerne faktisk når frem. Det går uden ekstra værktøjer med curl:
# Test konfigurationen og genindlæs
nginx -t && systemctl reload nginx
# Vis headerne for forsiden og en statisk fil
curl -sI https://www.example.de/ | grep -iE 'strict|content-security|x-content|x-frame|referrer|permissions|server'
curl -sI https://www.example.de/favicon.ico | grep -iE 'strict|x-content'
Typiske fejl er dobbelt satte headere, når webserver og applikation sender de samme headere, et foranliggende CDN, der fjerner eller overskriver headere, og headere, der kun optræder på forsiden, men ikke ved omdirigeringer eller fejlsider. Kontrollér desuden efter opdateringer af CMS'et eller af sikkerhedsudvidelser, om headerne har ændret sig.
Fastlæg derfor ét sted, hvor headerne vedligeholdes, helst webserveren eller den foranliggende tjeneste. Mange CMS-udvidelser tilbyder ligeledes indstillinger for sikkerhedsheadere. Det er bekvemt, men fører let til dobbelte eller modstridende oplysninger, hvis serveren desuden sætter headere. Til enkelte tests egner sig også browserens udviklerværktøjer: I netværksfanen ser I til hver forespørgsel svarheaderne, og konsollen viser overtrædelser af Content Security Policy.
Hvordan hjælper PHP SOS konkret?
- Vi gennemgår de aktuelle headere på alle jeres websites, også bag CDN og proxy, og påviser huller og modsigelser.
- Vi sætter headerne centralt i webserveren inden for rammerne af serverhærdningen og tester forside, undersider og fejlsider.
- Vi indfører Content Security Policy i Report-Only-tilstand, analyserer meddelelserne og sætter den på skarp efter aftale.
- Hvor kodeændringer ikke er mulige med det samme, supplerer vi beskyttelsen med WAF-regler og virtuel patching.
Ofte stillede spørgsmål
Hvad er security headers?
Security headers er tillægsoplysninger i webserverens svar. De fortæller f.eks. browseren, at den kun skal indlæse siden via HTTPS, ikke udføre fremmede scripts eller ikke vise siden i fremmede rammer. De beskytter først og fremmest de besøgende.
Beskytter security headers mod PHP2Shell?
Nej. PHP2Shell er en sårbarhed i PHP på serveren, headere virker i den besøgendes browser. Mod PHP2Shell hjælper opdateringen til en rettet PHP-version og genstarten af alle workere. Headere er en supplerende hærdning mod andre angrebstyper.
Kan en Content Security Policy ødelægge mit website?
Ja, en for streng politik blokerer nødvendige scripts, skrifttyper eller indlejret indhold. Derfor indfører man den først i Report-Only-tilstand, analyserer meddelelserne og skifter først derefter til håndhævelse.
Er X-XSS-Protection stadig fornuftig?
Nej. Aktuelle browsere vurderer ikke længere denne header, og anbefalingen lyder at udelade den eller sætte den til 0. Beskyttelse mod cross-site scripting yder ren escaping i koden og en Content Security Policy.