Wat is CSP en hoe stel je het veilig in?
Auteur: Redactie Domeny.ForSale Gepubliceerd
In het kort: CSP, oftewel Content Security Policy, is een beveiligingsmechanisme van de browser waarmee je bepaalt waarvandaan een pagina bronnen mag laden en welke code deze mag uitvoeren. Het helpt de gevolgen van XSS te beperken: het injecteren van een ongewenst script in een pagina. Met de juiste richtlijn beschermt CSP ook tegen het insluiten van de website in ongewenste frames. Je kunt het beleid het beste via een HTTP-responsheader doorgeven en eerst testen zonder bronnen te blokkeren.
Hoe werkt CSP en waartegen beschermt het?
Een browser laadt normaal gesproken de bronnen die in de paginacode staan: scripts, stylesheets, afbeeldingen en lettertypen. CSP voegt daar regels aan toe. Als een bron of de manier waarop code wordt uitgevoerd niet aan het beleid voldoet, blokkeert de browser die en registreert de overtreding in de ontwikkelaarstools.
De belangrijkste toepassing van CSP is het beperken van XSS-aanvallen (cross-site scripting). Bij zo’n aanval zorgt een aanvaller ervoor dat zijn script binnen de context van andermans website wordt uitgevoerd. Een kwetsbaarheid in een reactieformulier kan het bijvoorbeeld mogelijk maken om JavaScript-code in te voegen in plaats van gewone tekst. Een voldoende streng CSP-beleid kan voorkomen dat deze code wordt uitgevoerd, zelfs als de applicatie die ten onrechte op de pagina plaatst.
CSP helpt ook tegen clickjacking: het insluiten van een pagina in een frame, waarbij een misleidende laag de gebruiker ertoe verleidt op elementen van die pagina te klikken. Daarvoor dient de richtlijn frame-ancestors. Alleen regels voor scripts instellen biedt deze bescherming niet.
CSP verhelpt echter geen kwetsbaarheden in de applicatie. Correcte codering van uitvoergegevens, veilige verwerking van gebruikersinhoud en software-updates blijven nodig. Het beleid vormt een extra beveiligingslaag en vervangt deze maatregelen niet.
Waar stel je het CSP-beleid in?
De aanbevolen plek is de HTTP-responsheader met de naam Content-Security-Policy. De applicatie, webserver, reverse proxy of CDN kan deze toevoegen. De header moet samen met het HTML-document waarop het beleid van toepassing is naar de browser worden gestuurd.
Een deel van de regels kun je ook doorgeven via een meta-tag met het attribuut http-equiv="Content-Security-Policy". Deze oplossing heeft beperkingen: het beleid wordt pas actief nadat de tag is gelezen en ondersteunt noch rapportage zonder blokkering, noch de richtlijn frame-ancestors. Heb je toegang tot de configuratie van de HTTP-respons, kies dan voor de header.
Controleer ook of een andere laag van de infrastructuur al CSP toevoegt. Meerdere beleidsregels worden tegelijk afgedwongen: een extra header vervangt de vorige niet automatisch. Daardoor kan deze de werking van de website verder beperken.
De belangrijkste richtlijnen en een voorbeeldheader
Een richtlijn is één regel binnen het beleid. De richtlijnen worden gescheiden door puntkomma’s. Na de naam van elke richtlijn volgen de toegestane bronnen of speciale waarden.
| Richtlijn | Wat deze regelt |
|---|---|
default-src | Standaardbronnen voor veel soorten bronnen waarvoor geen eigen regel is ingesteld |
script-src | Bronnen van scripts en voorwaarden voor het uitvoeren van JavaScript |
style-src | Bronnen van stylesheets en regels voor het gebruik van inline stijlen |
img-src | Bronnen van afbeeldingen |
connect-src | Verbindingen die onder meer via fetch en WebSocket worden opgezet |
object-src | Ingesloten objecten die worden verwerkt door elementen zoals object |
base-uri | Adressen die in het element base zijn toegestaan |
frame-ancestors | Pagina’s die het document in een frame mogen insluiten |
Voor een eenvoudige website die uitsluitend eigen bestanden gebruikt, kan dit een uitgangspunt zijn:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
De waarde 'self' staat voor dezelfde oorsprong: hetzelfde schema, dezelfde hostnaam en dezelfde poort. 'none' staat geen enkele bron toe. Het bovenstaande voorbeeld verbiedt het insluiten van de pagina in frames en blokkeert onder meer scripts die rechtstreeks in HTML staan, evenals gebeurtenisattributen zoals onclick.
Dit is geen universele configuratie. Gebruikt de website een externe betaaldienst, analytics of lettertypen, dan moet je nagaan welke bronnen daarvoor nodig zijn en deze aan de juiste richtlijnen toevoegen. default-src vervangt niet alle regels: frame-ancestors moet bijvoorbeeld afzonderlijk worden opgegeven.
Hoe voer je CSP in zonder onbedoeld functies te blokkeren?
De veiligste aanpak is eerst vaststellen waarvan de website daadwerkelijk afhankelijk is en pas daarna blokkering inschakelen.
- Maak een overzicht van bronnen en integraties. Neem niet alleen de homepage mee, maar ook inloggen, formulieren, betalingen en de gebruikersomgeving.
- Stel de header
Content-Security-Policy-Report-Onlyin. De browser toetst het voorgestelde beleid en meldt overtredingen, maar blokkeert de betreffende bronnen of handelingen niet. Om rapporten automatisch te verzamelen, moet je ook het rapportagemechanisme en een ontvanger voor de rapporten configureren. - Test volledige gebruikersscenario’s. Controleer de console en het netwerkpaneel van de browser. Maak onderscheid tussen noodzakelijke bronnen, overbodige integraties en verzoeken die afkomstig zijn van browserextensies.
- Pas de regels en de code aan. Zet na het testen het beproefde beleid over naar
Content-Security-Policyen blijf na de invoering op fouten controleren.
Werk waarschuwingen niet weg door klakkeloos *, 'unsafe-inline' of 'unsafe-eval' toe te voegen. Zulke uitzonderingen kunnen de beveiliging aanzienlijk verzwakken. Voor noodzakelijke inline scripts kun je een nonce gebruiken, een onvoorspelbare waarde die voor elke respons wordt gegenereerd, of een hash: een digitale vingerafdruk van de inhoud van een specifiek script. De nonce moet in de header en in het scriptelement overeenkomen. Een vaste waarde die je in de configuratie plakt, voldoet daar niet aan.
Begin met beleid in rapportagemodus in een testomgeving en doorloop het hele traject, van het openen van de website tot het versturen van een formulier of het afronden van een aankoop. Zo zie je welke toestemmingen echt nodig zijn voordat CSP bronnen voor gebruikers gaat blokkeren.
Zie ook: Wat is MCP?
