Security headers toevoegen aan een WordPress thema

Beveiliging voor websites is tegenwoordig heel belangrijk. Wordt je gehackt sta je voordat je het weet misschien wel op Nu.nl of Tweakers.net. Lekt er bij die hack ook nog persoonlijke data weg dan spreek je over een datalek en kan je je mogelijk melden bij de Autoriteit Persoonsgegevens.

Om jouw WordPress website te beveiligen kan je gebruik maken van security headers. Dit zijn instellingen die ervoor zorgen dat o.a.:

  • Jouw website alleen via https:// bezocht mag worden
  • Dat niet zomaar externe CSS en JS bestanden ingeladen mogen worden
  • Dat de functie eval() in Javascript niet uitgevoerd mag worden
  • Er geen clickjacking uitgevoerd mag worden
  • Dat er geen XSS uitgevoerd mag worden

Heb je een maatwerk website, dus geen WordPress installatie, dan is het instellen van de headers heel makkelijk. Als programmeur weet je namelijk precies welke JS en CSS bestanden je extern inlaad of welke code wel of niet betrouwbaar is.

In de wereld van WordPress, met de vele thema’s en plugins, wordt het wat lastiger. Je hebt minder invloed op welke bestanden worden ingeladen, vanaf waar en wat voor code er uitgevoerd wordt. Iedere update van een plugin of thema kan invloed hebben op de instellingen.

Met het instellen van de security headers wordt je gedwongen om je te verdiepen in jouw website. Jij moet precies weten welke bestanden of code je wel of niet kan vertrouwen. Onderstaande functie kan je plaatsen in het functions.php bestand van je thema.

De functie:

function child_theme_headers() {
    // Set values for the content secure policy:
    $cspSources = ["default-src *.domein.nl *.wp.com",
                   "script-src 'unsafe-inline' *.domein.nl *.googleapis.com *.wp.com",
                   "style-src 'unsafe-inline' *.domein.nl *.googleapis.com *.wp.com *.bootstrapcdn.com",
                   "font-src data: *.domein.nl fonts.gstatic.com *.wp.com wordpress.com *.bootstrapcdn.com",
                   "media-src *.domein.nl",
                   "img-src data: *.domein.nl *.wp.com"];

    // Enforce the use of HTTPS
    header("Strict-Transport-Security: max-age=31536000; includeSubDomains");
    // Prevent Clickjacking
    header("X-Frame-Options: SAMEORIGIN");
    // Prevent XSS Attack
    header("Content-Security-Policy: " . implode('; ', $cspSources)); // FF 23+ Chrome 25+ Safari 7+ Opera 19+
    header("X-Content-Security-Policy: " . implode('; ', $cspSources)); // IE 10+
    // Block Access If XSS Attack Is Suspected
    header("X-XSS-Protection: 1; mode=block");
    // Prevent MIME-Type Sniffing
    header("X-Content-Type-Options: nosniff");
    // Referrer Policy
    header("Referrer-Policy: no-referrer-when-downgrade");
    // Feature Policy
    header("Feature-Policy: gyroscope 'self'; fullscreen 'self'");
}
add_action( 'send_headers', 'child_theme_headers' );

De toelichting

Strict-Transport-Security
Hiermee verplicht je dat browsers jouw websites alleen via https:// mogen inladen. Voor meer informatie zie hstspreload.org waar je ook je instellingen kan testen.

X-Frame-Options
Hiermee geef je aan of jouw website in een iframe ingeladen mag worden. Met de instelling SAMEORIGIN kan jouw website niet ingeladen worden op een andere website omdat de origin verschilt.

Content-Security-Policy voor Chrome / Safari / Opera / Firefox
Content-Security-Policy voor IE 10 en IE 11
Hiermee geef je op welke CSS, JS, fonts en/of lettertypen vanaf waar ingeladen mogen worden. Hierover lees je aan het einde van dit blog meer omdat er vele mogelijkheden zijn.

X-XSS-Protection
Browsers blokkeren de toegang wanneer ze vermoeden dat een XSS aanval wordt uitgevoerd. XSS is ook wel bekend onder de naam Cross-site scripting.

X-Content-Type-Options
Met deze optie proberen browsers niet te bepalen wat het MIME-TYPE is door eraan te ruiken (sniffen). Ze luisteren alleen naar de MIME-TYPE zoals die door de website opgegeven is.

Referrer-Policy
Bepaald hoe de browser om moet gaan met de referrer. Met de instelling zoals hierboven opgegeven zal de browser de referrer niet doorgeven als er van https:// naar http:// wordt gegaan.

Feature-Policy
Deze security header is nog geen maand oud. Hiermee kan je opgeven welke browser functionaliteiten of API’s gebruikt mogen worden. Functionaliteiten die je bijvoorbeeld uit kan zetten zijn notificaties, push berichten, microfoon, gyrometer etc. Lees dit artikel voor meer informatie over deze security header.

Content security policy

Een content security policy bestaat uit een aantal soorten. Je bepaald zelf welke soorten je opgeeft. Hoe meer in detail je ze instelt hoe veiliger de website wordt. Nadeel hiervan is dat de instellingen er ook voor kunnen zorgen dat bepaalde functionaliteiten opeens niet meer werken. Daarom testen, testen en nog eens testen.

  • default-src = de fall back als een ander soort niet toereikend is
  • script-src = de instellingen voor Javascript bestanden en inline code
  • style-src = de instellingen voor CSS bestanden en inline code
  • font-src = de instellingen voor lettertype bestanden
  • media-src = de instellingen voor muziek / video intern en extern
  • img-src = de instellingen voor afbeeldingen intern en extern

Per soort kan je opgeven vanaf welke website deze toegankelijk mogen zijn. In bovenstaand voorbeeld zie je bij script-src dat bestanden vanaf *.domein.nl, *.googleapis.com en *.wp.com ingeladen mogen worden. Het sterretje dient als wildcard wat betekent dat www.domein.nl, fiets.domein.nl en zandbak.domein.nl worden geaccepteerd. Je kan ook alle mogelijkheden uitschrijven.

Bij script-src en style-src zie je ook de waarde ‘unsafe-inline’ staan. Dit is een waarde die je liever niet gebruikt, maar voor WordPress kan je niet zonder. Met deze waarde sta je toe dat inline Javascript of CSS code uitgevoerd mag worden. Voor CSS is dit nog niet een probleem maar voor Javascript zou het best kunnen gaan om onveilige code.

Bij feature-policy zie je de waarde ‘self’ staan. Dat betekent dat deze functionaliteiten alleen gebruikt kunnen worden door de website zelf maar niet via een andere website.

Bovenstaande functie gebruik ik voor mijn eigen website. Het kan dus best zo zijn dat voor jouw website andere domeinen opgegeven moeten worden. Hier kom je het makkelijkste achter door gebruik te maken van de “developer toolbar” en dan de optie “console”.

Hoe kan ik de security headers testen

Dat kan je doen via https://securityheaders.com.

Het thema is niet van mij en ik heb geen child theme

Je kan dan het beste een drop-in maken. Dit is een simpele plugin die je in de plugins map plaatst. Zie oplossing 2 in dit blog voor een voorbeeld.

Conclusie

Ben je nu 100% veilig met bovenstaande functie wat security headers betreft. Helaas ik moet je teleurstellen maar het antwoord is “nee”. Zoals je hebt gelezen zijn de instellingen ruim opgezet om te voorkomen dat je te snel tegen grenzen aanloopt. Het gaat ook een beetje in tegen het principe van WordPress om gemakkelijk functionaliteiten toe te kunnen voegen of juist weer te verwijderen.

Het blijft belangrijk om op regelmatige basis de instellingen te controleren of deze nog juist zijn.

Meer informatie

Wil je meer lezen over dit onderwerp dan is de website van Scott Helme een goed startpunt.

Laat een reactie achter

Deze website gebruikt Akismet om spam te verminderen. Bekijk hoe je reactie-gegevens worden verwerkt.