Waarom je een sterke Content Security Policy nodig hebt
door Sebastian Grimm
Security SpecialistHet Belang van Beveiligingsheaders
Toen browsers voor het eerst werden ontworpen, had niemand kunnen voorspellen welke soorten aanvallen uiteindelijk mogelijk zouden worden. Sommige van de aanvallen die we vandaag kennen, zouden mogelijk geëlimineerd of op zijn minst beperkt kunnen worden door te veranderen hoe browsers werken. Het veranderen van de werking van browsers zou echter een grote impact hebben op bestaande internetdiensten, waardoor het geen haalbare optie is. Het alternatief? We bieden gebruikers met hogere beveiligingsbehoeften de mogelijkheid om extra beschermingslagen toe te voegen, bekend als beveiligingsheaders. Wanneer een site wordt bezocht, reageert de server met een HTTP-responsheader. Dit is een extra instructie voor je browser, waardoor jouw deel van het internet—je website of webapplicatie—veiliger wordt.
Wat is een CSP?
Content Security Policy, of kortweg CSP, is een voorbeeld van zo'n beveiligingsheader [1,2]. Het idee is eenvoudig: een CSP beperkt wat een browser kan doen met content en waar die content vandaan mag komen. In de standaardinstelling zijn er weinig beperkingen, wat betekent dat een website content van bijna elke bron op het internet kan laden. Dit omvat ogenschijnlijk onschuldige dingen zoals afbeeldingen, maar ook JavaScript-code die direct in de browser wordt uitgevoerd. Met een CSP bepaal jij als website-eigenaar precies waar content vandaan mag komen en onder welke voorwaarden.
Zie de CSP als je tweede verdedigingslinie. Als een aanvaller erin slaagt een kwetsbaarheid te vinden, maakt de CSP het veel moeilijker voor hen om deze te misbruiken. Laten we een concreet voorbeeld bekijken.
Het Gevaar van Cross-Site Scripting
Frontend content- en code-injectie kwetsbaarheden zijn al lang een bekend probleem. Dit is een klasse van kwetsbaarheden waarbij data, zoals tekst die door een gebruiker is ingediend, niet correct wordt verwerkt door de applicatie. Dit stelt een aanvaller in staat om de beveiliging te omzeilen en hun eigen markup (HTML), styling (CSS) of client-side code (JavaScript) toe te voegen aan de webapplicatie. Dit is vooral gevaarlijk met JavaScript, omdat het een aanvaller in staat stelt client-side code uit te voeren in de browser van het slachtoffer. Dit staat bekend als cross-site scripting (XSS) en geeft een aanvaller volledige controle over de applicatie alsof hij is ingelogd als het slachtoffer.
Je zou kunnen denken: "Maar als mijn applicatie niet kwetsbaar is voor XSS, voegt een CSP dan niets toe?" Weet je echt zeker dat je niet kwetsbaar bent? XSS is misschien een van de 'oudere' aanvalsmethoden, maar het blijft een probleem dat veel organisaties treft. Meer dan 30% van de applicaties die Computest Security het afgelopen jaar heeft getest, waren kwetsbaar voor een of andere vorm van XSS [3]. Houd er rekening mee dat de gemiddelde klant van Computest Security al zeer beveiligingsbewust is en regelmatig beveiligingstests op hun applicaties uitvoert. Daarom is het werkelijke aantal XSS-kwetsbare applicaties waarschijnlijk nog hoger. Het is geen luxe om een sterke CSP in te stellen. Het kan die extra beveiliging bieden die je nodig hebt om onbekende risico's te beperken.
Hoe Werkt CSP?
Zoals bij elke interessante vraag is het antwoord: het hangt ervan af. In dit geval hangt het af van je applicatie en hoe deze is opgebouwd. Laten we enkele voorbeelden bekijken van mogelijke CSP's die als HTTP-responsheaders worden teruggegeven.

Door te focussen op de script-src-richtlijn, die alle JavaScript-bronnen zoals *.js-bestanden of inline code tussen -tags beheert, beschermt deze richtlijn je tegen kwetsbaarheden met de grootste impact.
Als je applicatie (https://example.com) zo is ingesteld dat alle gebruikte JavaScript afkomstig is van een toegewijd domein (https://js.example.com), dan kan een CSP die je beschermt tegen veel soorten XSS-aanvallen er als volgt uitzien:

Elke script die van een andere bron wordt geladen, zal niet worden uitgevoerd. Hetzelfde geldt voor elke inline JavaScript. Als scripts ook moeten worden opgenomen van hetzelfde domein dat de applicatie host, kan het er als volgt uitzien:

Het toestaan van inline JavaScript maakt het iets complexer omdat een browser niet kan onderscheiden tussen legitieme en kwaadaardig geïnjecteerde inhoud. Toch is dit mogelijk met nonces of hashes. Een nonce, een voldoende willekeurige waarde, kan als volgt in de CSP-header worden opgenomen:

Deze waarde moet overeenkomen met de waarde die is opgegeven in een -tag in dezelfde respons.

Als de juiste nonce niet wordt meegeleverd, wordt de code niet uitgevoerd. De nonce-waarde verandert bij elk verzoek, waardoor een aanvaller deze niet van tevoren kan voorspellen, wat elke potentiële XSS-kwetsbaarheid onbruikbaar maakt. Een alternatieve methode is het gebruik van een hashwaarde, berekend over de volledige inhoud van de -tag, waarbij niet-overeenkomende hashes betekenen dat er geen uitvoering plaatsvindt. Dit voorkomt dat een aanvaller zijn kwaadaardige code injecteert.
Als je je applicatie niet hebt ontwikkeld met een CSP in gedachten, kies dan een oplossing die bij je architectuur past. Gelukkig bestaan er bibliotheken voor verschillende webapplicatieframeworks om de implementatie te ondersteunen.
De hier gegeven voorbeelden tonen niet alle mogelijkheden van een CSP. Het maakt gedetailleerde configuraties mogelijk voor alle potentiële bronnen in een HTML-pagina. Geïnteresseerd? Links aan het einde van deze blog bieden verder leesmateriaal.
Implementatiefouten met een CSP
Wees voorzichtig, er kan van alles misgaan bij het implementeren van een CSP. Vooral bij het gebruik van de whitelist-benadering van bronnen bestaan valkuilen. Bij Computest Security hebben we vaak gezien dat één verkeerd geconfigureerde CSP nutteloos wordt of gemakkelijk kan worden omzeild door een aanvaller. Voorbeelden van dergelijke fouten zijn:
- Als je 'unsafe-inline' opneemt in de script-src-richtlijn, staat dit alle inline JavaScript toe. Zoals de naam al aangeeft, brengt dit een hoog risico met zich mee en tenietdoet het de meeste voordelen van een CSP.
- Wanneer bestanden kunnen worden geüpload naar en gedownload van het applicatiedomein, is er een groot risico dat dit kan worden misbruikt om een CSP te omzeilen die ‘self’ toestaat in de script-src-richtlijn, waardoor je applicatie kwetsbaar wordt.
- Als je een CDN of openbare bronhost zoals AWS S3 toestaat (bijv. https://s3.eu-central-1.amazonaws.com), kan een aanvaller deze diensten gebruiken om hun kwaadaardige exploits te hosten. Iedereen kan een AWS-account aanmaken om bronnen op S3 te hosten, wat potentiële risico’s met zich meebrengt.
- Als je nonces gebruikt, moeten deze voldoende willekeurig zijn en slechts één keer worden gebruikt. Anders kan een aanvaller de nonce hergebruiken voor zijn aanvallen.
- Als je inline JavaScript toestaat met een nonce-waarde, beschermt de CSP niet tegen JavaScript-injectie direct in het script. Een -tag die is goedgekeurd met een nonce-waarde wordt altijd uitgevoerd, ongeacht de inhoud.
- Toegestane hosts met JSONP-eindpunten kunnen door aanvallers worden misbruikt om een CSP gedeeltelijk te omzeilen door misbruik van de callback-functionaliteit, wat mogelijk willekeurige JavaScript-uitvoering toestaat.
Vanwege deze veelvoorkomende misconfiguraties wordt een nonce- of hash-gebaseerde CSP in combinatie met 'strict-dynamic' over het algemeen als de meest veilige aanpak beschouwd [4]. Dit stelt je in staat precies te specificeren welke scripts mogen worden uitgevoerd zonder de hele host te hoeven whitelisten. Een voorbeeld van hoe dit eruit kan zien:

Extra inhoud kan dan binnen de HTML worden opgenomen:

Een goed doordacht en strikt Content Security Policy bepaalt precies wat er in de browser kan gebeuren wanneer uw applicatie wordt geladen. Hoewel een sterke CSP niet garandeert dat uw applicatie volledig beschermd is tegen alle externe aanvallen, zet het u op het juiste pad naar een veiligere online omgeving.
Geïnteresseerd om te zien of uw organisatie baat zou hebben bij een CSP? Wij helpen u graag! Neem contact met ons op via [email protected] of bel +31 (0)88 733 13 37 en wij nemen snel contact met u op.
Voor meer informatie over CSP:

