HTTP Headers Content-Security-Policy

Content-Security-Policy .htaccess- HTTP - MDN Web Docs

Headers Content Security Policy (CSP)

Binnenland: Tech HTTP Headers Content-Security-Policy: Consent-beveiligingsbeleid, Security Policy (CSP) probeert deze problemen op te lossen door een website toe te staan exact te vermelden welke bronnen op een website moeten worden geladen. Eigenaren van websites zouden in theorie exact moeten weten welke bronnen hun website het nodig heeft, dus waarom zou u de webbrowser niet vertellen om iets anders te laden?

Content-Security-Policy is de naam van een HTTP-responsheader die moderne browsers gebruiken om de beveiliging van het document (of webpagina) te verbeteren.Met de header Content-Security-Policy kunt u beperken hoe bronnen zoals JavaScript, CSS of vrijwel alles dat de browser laadt. Hoewel het voornamelijk wordt gebruikt als HTTP-responsheader, kunt u het ook toepassen via een metatag. De term Content Security Policy wordt vaak afgekort als CSP. Welke soorten aanvallen helpt Content-Security-Policy te verminderen? CSP is in eerste instantie ontworpen om het aanvalsoppervlak van Cross Site Scripting (XSS)-aanvallen te verkleinen, latere versies van de specificatie beschermen ook tegen andere vormen van aanvallen, zoals Click Jacking.

Cross-site scripting (XSS)

Een webbrowser is een enorm krachtig en veelzijdig stuk software, dat in staat is om bronnen van over het hele internet te laden om een ​​website te vormen. Dit maakt het een beveiligingsnachtmerrie! Extra code kan op verschillende manieren in uw website worden opgenomen

Cross-site scripting (XSS) staat bijna altijd bovenaan de beveiligingslijst van web kwetsbaarheden (het is nummer drie in de nieuwste OWASP Top 10). Dit houdt in feite in dat u ongeautoriseerde JavaScript op een webpagina plaatst. Dit kan op verschillende manieren worden gedaan, bijvoorbeeld door een zoekfunctie op uw website te gebruiken en de zoekterm bovenaan de pagina te printen.

Evenzo zou een zoekopdracht naar <script> alert (1); </ script> bovenaan de pagina een <script> alert (1); </ script> afdrukken, en uw browser zou dit javascript herkennen en het uitvoeren en poppen een waarschuwing genereren. Dit is slechts één manier om javascript in te voeren (en wordt beschermd op deze website dus verspil niet eens je tijd aan het zoeken).

Andere manieren zijn misschien een opmerking plaatsen op een site met een gedeelte met opmerkingen (zoals deze). Op die manier zal elke andere bezoeker van de website die opmerking laden en elke javascript uitvoeren (opnieuw zou dit niet op deze website moeten gebeuren, aangezien ons reactiesysteem van Disqus controleert op deze aanvallen). Andere manieren compromitteren andere inhoud die u op uw site laadt (bijvoorbeeld als u een stukje code van een andere website op uw website laadt voor bijvoorbeeld een mooie animatie).

Hoewel javascript waarschijnlijk het gevaarlijkste item is dat op uw website is geïnjecteerd, kan andere inhoud ook problemen veroorzaken. CSS kan worden gebruikt om inhoud te verbergen, bijvoorbeeld door een formulier te vervangen waarin u een creditcard opgeeft met een ander formulier dat gegevens naar een aanvaller verzendt. Er kunnen 1 pixelafbeeldingen worden gebruikt om gebruikers via internet te volgen. Frames kunnen worden gebruikt om paginaweergaven te laden, gebruikers bandbreedte te verspillen en valse hits op een andere site te maken.

Hoe HTTP Headers Content-Security-Policy op te zetten

LEES DIT ZEER GOED, EN BESLIS LATER WELKE OPTIE

Een CSP policy wordt ingesteld door een HTTP header in een bepaald formaat te verzenden. Echter komt het zeer vaak voor, dat de Content-Security-Policy, zeer moeilijk toe te voegen is aan de .htaccess bestand. Het is dan ook verstandig om dit stuk meerdere malen door te lezen voordat je er echt aan zult beginnen. Je hebt hem wel nodig in het geheel

Verander jouwwebsite.nl naar jouw URL,

Header always set Content-Security-Policy: "default-src 'self' https:jouwwebsite.nl; script-src 'self'; style-src 'self';"

Hierin staat dat, tenzij anders aangegeven, bronnen kunnen worden geladen vanaf deze website en elke andere website waarop HTTPS wordt uitgevoerd. Javascript kan alleen worden geladen vanaf deze website, net als CSS-stijlen. Dus dit stopt alle inline-scripts en ook eventuele externe scripts die worden geladen. Een dergelijk beleid zou in wezen betrekking hebben op XSS voor uw site.

Andere belangrijke opties zijn onder meer de mogelijkheid om een rapportagemechanisme toe te voegen voor eventuele schendingen van het beleid om JSON-rapporten naar een opgegeven URL te verzenden:

Header always set Content-Security-Policy: "default-src 'self' https:; \ script-src 'self'; style-src 'self'; \ report-uri https://www.blablabla.com/api/report/csp-report.json;"

Hiermee kunt u controleren of delen van uw website worden geblokkeerd, door een verkeerd beleid of vanwege een onjuiste browserimplementatie.

Er is ook de optie om in de rapportmodus alleen te werken, die rapporten terugstuurt, maar niet blokkeert dat bronnen worden geladen:

Header always set Content-Security-Policy-Report-Only: "default-src 'self' https:; \ script-src 'self'; style-src 'self'; \ report-uri https://www.blablabla.com/api/report/csp-report.json;"

Dit wordt ten zeerste aanbevolen voordat u CSP implementeert, om te testen of uw beleid klopt en niet per abuis de bronnen blokkeert die uw website nodig heeft. Dit is met name het geval als u een grote website met veel pagina's uitvoert, en u kunt er niet 100% zeker van zijn dat uw beleid betrekking heeft op alle bronnen op elke pagina.

Ofwel rapportagemethode (of blok en rapport met Content-Security-beleid of alleen rapport met Content-Security-Policy-Report-Only), vereist dat een service wordt opgezet om naar de rapporten te luisteren. Bekijk hiertoe rapport-uri, om u te besparen bij het opzetten van uw eigen, hoewel het instellen van uw eigen is net zo eenvoudig als het maken van iets dat luistert naar JSON POST requests en deze vervolgens uitvoert.

Een eenvoudig voorbeeld van de NodeJS-service die wordt weergegeven in de lijst met CSP en HPKP en deze gewoon bij een logbestand registreert, wordt hieronder weergegeven:

'use strict'
var express = require('express'),
bodyParser = require('body-parser'),
debug = require('debug')('ReportService'),
errorhandler = require('errorhandler'),
morgan = require('morgan'),
compression = require('compression');

var app = express();
app.disable('x-powered-by');
app.use(errorhandler({
dumpExceptions: true,
showStack: true
}));
//app.use(express.json());
app.use(morgan(
'dev', {
immediate: true
}));

app.use(compression());

app.use(function(req, res, next) {

//Some browsers (Chrome at least) doesn't set the content type for HPKP
//Reports which causing the body parser to ignore the content, so add the content type.

if(typeof(req.headers['content-type']) === 'undefined'){
req.headers['content-type'] = "application/json; charset=UTF-8";
}
next();
})

// parse various different custom JSON types as JSON

app.use(bodyParser.json({ type: 'application/json' }));
app.use(bodyParser.json({ type: 'application/csp-report' }));

app.get('/test/', function (req, res) {
res.send('I am running!\n');
});

app.get('/report/csp-report.json', function (req, res) {
res.status(403);
res.send('Should only be a POST request!');
});

app.get('/report/hpkp-report.json', function (req, res) {
res.status(403); res.send('Should only be a POST request!');
});

app.post('/report/csp-report.json', function (req, res) {
debug('debugReport for CSP:' + '{"Headers":' + JSON.stringify(req.headers) + ',"Body":' + JSON.stringify(req.body) + "}"); res.send('Thanks for reporting');
});

app.post('/report/hpkp-report.json', function (req, res) {
debug('debugReport for HPKP:' + '{"Headers":' + JSON.stringify(req.headers) + ',"Body":' + JSON.stringify(req.body) + "}"); res.send('Thanks for reporting');
});

app.listen(3002);
debug(JSON.stringify(3002) + ":port starting");

Ik zou echter wel een waarschuwing moeten geven over het instellen van een rapport-uri-optie: ze zijn erg, erg luidruchtig. Veel browser extensies injecteren inhoud op de pagina, wat uiteraard CSP blokkeert, maar vervolgens weer rapporteert naar uw uri-url-URL. Nu zijn rapporten alleen echt handig als er iets is waar u actie op kunt ondernemen (bijvoorbeeld als waarschuwing voor een onjuist CSP beleid), maar voor browseruitbreidingsrapporten is er niet veel dat u kunt doen, behalve negeren (wat eenvoudiger gezegd is) dan gedaan en voegt het risico toe dat een echte waarschuwing ten onrechte als vals positief wordt aangemerkt), of laat hen toe om de ruis te verminderen (wat leidt tot een meer laks beleid dan u echt wilt hebben). Geen van beiden is geweldig.

Het bovenstaande beleid staat geen inline-scripts toe, wat u in een zeer specifiek geval zou willen. Deze website maakt bijvoorbeeld gebruik van Google Analytics, wat wordt aanbevolen als inline-script op de pagina en vervolgens de JavaScript-code van de Google-servers. Het bovenstaande beleid voorkomt dat het inline-script en het Google-script worden geladen. U zou de onveilige inline beleidsoptie voor het inline script kunnen gebruiken:

In onze test resultaten, kwam herhaaldelijk een foutmelding op unsafe-inline

Header always set Content-Security-Policy: "default-src 'self' https:; \ script-src 'self' 'unsafe-inline' https://www.google-analytics.com;"

Maar dat opent uw website voor alle <script> -tags overal op de pagina. CSP 2 voegt de opties voor hashes toe, waar u een hash kunt berekenen op basis van de tekst van het script en die hasj kunt gebruiken in plaats van alle inline-scripts met onveilige inline. Het nieuwe beleid ziet er als volgt uit:

Header always set Content-Security-Policy: "default-src 'self' https:; script-src 'self' \ 'sha256-iLa0hRPsoDjvxFYYu-uNM5UI6luIzGqIS_ir0v4_XH0=' https://www.google-analytics.com;"

De gemakkelijkste manier om de hash te vinden die btw nodig heeft, is om de pagina in Google Chrome te laden met het beleid zonder de has, en naar de console te kijken in Developer Tools die u handig de hash vertelt die u aan uw beleid moet toevoegen:

#

Een andere optie, vergelijkbaar met het gebruik van hashes, is om een willekeurig gegenereerde nonce value te gebruiken. Dit is iets ingewikkelder om in te stellen, afhankelijk van de technologie op uw website, maar zou inhouden het genereren van een willekeurig nummer en het instellen van dat willekeurige nummer als een parameter op de scripttag (<script nonce-RANDOMNUMBER>), en vervolgens die willekeurige toe te voegen nummer naar de CSP-header die wordt geretourneerd wanneer die pagina wordt aangevraagd.

Merk op dat wanneer u een hash of een nonce specificeert, de meeste browsers automatisch elke unsafe-eval optie uit uw polis verwijderen in de veronderstelling dat u beide niet nodig heeft. Dit kan problemen veroorzaken als u hashes wilt toevoegen en er zijn er een paar te vinden op uw site - het wordt een alles of niets optie. Firefox heeft een nog slechtere implementatie, waarbij inclusief hashes unsafe-eval uitzetten, maar hashes worden niet ondersteund, wat betekent dat alle inline scripts plotseling worden uitgeschakeld! Deze bug (hier bijgehouden en die nu lijkt te zijn opgelost) is in feite gestopt, zodat u hashes helemaal niet meer kunt gebruiken, zelfs niet voor browsers die deze wel ondersteunen, zoals Chrome. Firefox print ook een foutmelding dat hetzelfde gebeurt voor nonces, maar dan gaat het door en laadt de bron sowieso!

Een laatste ding om op te merken is dat het beleid alleen echt nodig is op de hoofdpagina, en niet op alle andere bronnen (CSS bestanden, Javascript bestanden, afbeeldingen, lettertypen ... enz.). Dit is met name belangrijk omdat het beleid vrij groot kan worden en dus het terugsturen van alle bronnen uiteindelijk een beetje zonde is.

Dit kan eenvoudig worden ingesteld, in Apache met config zoals het volgende:

<FilesMatch "\.(htm|html|php)$">
<IfModule mod_headers.c>
Header always set Content-Security-Policy: "default-src 'self' https:; \ script-src 'self'; style-src 'self';"
</IfModule>
</FilesMatch>

Dit veronderstelt dat u alleen .htm-, .html- of .php-bestanden retourneert, maar dit kan worden uitgebreid tot zoveel extensies als u nodig hebt. Ik heb geen manier gevonden om deze header te verzenden op basis van het teruggegeven MIME-type (bijvoorbeeld tekst/html).