Direct naar de inhoud

Cookie-instellingen

Kies per soort welke cookies je toestaat. Je kunt je keuze altijd wijzigen via Cookie-instellingen onderaan elke pagina. Privacyverklaring

Noodzakelijk

Altijd aan

Nodig om in te loggen, je winkelwagen te bewaren en je keuzes te onthouden. Deze staan altijd aan.

Welke cookies?
  • weboke_sessie, weboke_klant, weboke_remember: je sessie en ingelogd blijven
  • weboke_basket: je winkelwagen
  • wkBtwIncl: prijzen met of zonder btw tonen
  • wok_cookies: je cookiekeuze, 12 maanden

Meet welke advertentie tot een bezoek of bestelling leidt, zodat we niet betalen voor advertenties die niets doen.

Welke cookies?
  • Google Ads via Google Tag Manager (_gcl_au, _gcl_aw), tot 90 dagen
  • OpenAI Ads, advertenties in ChatGPT
  • wok_aff: via welke partner je bij ons kwam (affiliateprogramma), 60 dagen

4,6

Land en taal

Elk land heeft zijn eigen site, met prijzen en btw van dat land.

Bekijken

Module 7 · 7.4

De site verharden: rechten, headers en beveiligingsplugins

Module 7: Beveiliging · Leestijd: 10 minuten

Leerdoel: Na deze les kun je een WordPress-site verharden met rechten, instellingen en beveiligingsheaders, en beveiligingsplugins op hun waarde schatten.

Kernbegrippen: verharden (hardening), bestandsrechten (644, 755), DISALLOW_FILE_EDIT, geen PHP in uploads, mappenlijst, versie verbergen, X-Powered-By, beveiligingsheaders, back-upbestanden en .git in de webmap, WAF op de server, WAF in een plugin, malwarescanner

Wat verharden is

Verharden betekent: de site zo instellen dat een fout of een lek minder schade kan doen. Het vervangt updates en sterke wachtwoorden niet (les 7.2 en 7.3), maar maakt de gevolgen kleiner. Denk aan een huis: updates zijn de sloten, verharden is ervoor zorgen dat een inbreker die toch binnen is, niet bij de kluis kan.

Bestandsrechten

Elk bestand en elke map op de server heeft rechten: wie mag lezen, schrijven en uitvoeren. Ze worden geschreven als drie cijfers, voor de eigenaar, de groep en de rest van de wereld. De richtlijn uit de documentatie van WordPress:

WatRechtenBetekenis
Mappen755Eigenaar mag alles, anderen mogen lezen en openen
Bestanden644Eigenaar mag lezen en schrijven, anderen alleen lezen
wp-config.phpstrenger, bijvoorbeeld 600 of 640Alleen de eigenaar (en eventueel de webservergroep) mag lezen

Welke waarde voor wp-config.php werkt, hangt af van hoe je hoster PHP draait: bij de meeste gedeelde hosting draait PHP als jouw eigen gebruiker, en dan is 600 genoeg. Probeer het en kijk of de site nog werkt.

Nooit 777. Dat betekent: iedereen op de server mag schrijven. Een handleiding die zegt "zet de map op 777 als het uploaden niet werkt", lost het probleem verkeerd op. Bij goede hosting is dat ook nooit nodig.

Instellingen in wp-config.php

Een paar regels die veel schelen (boven "stop met bewerken"):

// Geen bestanden bewerken vanuit het beheer (Weergave > Thema-editor en Plugins > Plugin-editor).
define( 'DISALLOW_FILE_EDIT', true );

// Foutmeldingen nooit op het scherm van bezoekers (les 5.4).
define( 'WP_DEBUG', false );

Met DISALLOW_FILE_EDIT verdwijnt de editor waarmee je in het beheer PHP-bestanden van thema's en plugins kunt aanpassen. Een inbreker die een beheerdersaccount overneemt, kan dan niet met twee klikken kwaadaardige code in je thema zetten. Je kunt nog steeds plugins installeren; wil je dat ook verbieden (bijvoorbeeld bij een site die je voor een klant beheert), dan is er DISALLOW_FILE_MODS, maar dan werken ook updates via het beheer niet meer.

Geen PHP in uploads, geen mappenlijst

In wp-content/uploads horen afbeeldingen en documenten, nooit PHP-bestanden. Inbrekers die via een lek een bestand kunnen uploaden, proberen er juist een PHP-bestand neer te zetten en dat op te vragen. Blokkeer dat met een .htaccess in de map uploads (bij LiteSpeed en Apache):

<Files *.php>
Require all denied
</Files>

Zet ook het tonen van mappen uit. Zonder index.php of index.html in een map laten sommige webservers een lijst van alle bestanden zien ("Index of /wp-content/uploads/2026/11"). Dat is een etalage voor wie zoekt naar back-ups of gevoelige documenten. In de .htaccess van je webmap:

Options -Indexes

Veel hosters hebben dit al standaard uitgezet. De opdracht van deze les controleert het.

Geen restjes in de webmap

Alles in de webmap is via het web op te vragen, behalve wat de server als PHP uitvoert of blokkeert. Gevaarlijk zijn:

  • kopieën van wp-config.php (wp-config.php.bak, wp-config.old, wp-config.php~ van een teksteditor): die bevatten je databasewachtwoord en worden als tekst opgestuurd (les 1.3);
  • back-ups als backup.zip, site.tar.gz of database.sql in de webmap;
  • een .git-map van een ontwikkelaar, waarmee iemand je hele code (en soms wachtwoorden) kan downloaden;
  • debug.log in wp-content (les 5.4);
  • oude installatie- of testbestanden zoals info.php met phpinfo().

Bewaar back-ups buiten de webmap of buiten de server, en ruim restjes op.

Versie verbergen: kleine winst

WordPress zet standaard in de HTML:

<meta name="generator" content="WordPress 7.1.4" />

en hetzelfde in de RSS-feed. Ook PHP meldt zich soms in een kopregel: X-Powered-By: PHP/8.3.14. Dat verbergen is redelijk, maar verwacht er niet te veel van: de programma's van inbrekers proberen een lek gewoon, ongeacht de versie die je toont, en versies zijn vaak ook af te leiden uit ?ver= achter scripts. Verbergen is opruimen, geen beveiliging. Een site die zijn versie verbergt maar niet bijwerkt, is net zo kwetsbaar.

Zo doe je het, in een eigen kleine plugin of in functions.php van je child theme:

remove_action( 'wp_head', 'wp_generator' );
add_filter( 'the_generator', '__return_empty_string' );

En de PHP-kopregel met expose_php = Off in de PHP-instellingen van je hoster (bij DirectAdmin in Select PHP version, Options), of met Header unset X-Powered-By in .htaccess.

Beveiligingsheaders

Met een paar kopregels vertel je de browser hoe hij met je site moet omgaan. De belangrijkste:

KopregelWat hij doet
Strict-Transport-SecurityAlleen nog via https (les 3.1)
X-Content-Type-Options: nosniffDe browser gaat niet raden wat voor bestand iets is; voorkomt dat een geüpload "plaatje" als script wordt uitgevoerd
X-Frame-Options: SAMEORIGIN of Content-Security-Policy: frame-ancestors 'self'Andere sites mogen jouw site niet in een frame tonen; voorkomt clickjacking (een onzichtbare knop van jouw site onder die van een ander)
Referrer-Policy: strict-origin-when-cross-originBij een klik naar een andere site gaat alleen je domeinnaam mee, niet het volledige adres
Permissions-PolicyZet browserfuncties uit die je site niet gebruikt (camera, microfoon, locatie)
Content-Security-PolicyBepaalt precies van welke bronnen scripts en stijlen mogen komen. Krachtig, maar lastig goed te krijgen met WordPress en plugins; begin met de modus Report-Only

In .htaccess (bij LiteSpeed en Apache):

<IfModule mod_headers.c>
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=()"
</IfModule>

Test daarna of alles werkt: ingesloten inhoud, betaalknoppen, een chatwidget. Externe tools zoals securityheaders.com en internet.nl laten zien wat je site stuurt.

Beveiligingsplugins, eerlijk bekeken

Er zijn veel beveiligingsplugins (bijvoorbeeld Wordfence, Solid Security, All-In-One Security, Sucuri). Ze bundelen vaak: een firewall, een malwarescanner, inlogbeveiliging, tweestapsverificatie, meldingen en een verhardingslijst. Nuttig, maar met grenzen:

  • Een firewall in een plugin (WAF) start pas als PHP draait. Een kwaadaardig verzoek moet eerst door de webserver en PHP heen voordat de plugin hem ziet. Een lek in een PHP-bestand dat rechtstreeks wordt aangeroepen, of een aanval die PHP zelf zwaar belast, houdt hij niet altijd tegen. Een firewall op de server (bijvoorbeeld ModSecurity, Imunify360 of een firewall van je hoster) zit eerder in de keten en stopt meer, zonder dat jouw pakket het rekenwerk doet. Vraag je hoster wat er op de server draait.
  • Een scanner vindt achteraf. Een malwarescanner vertelt je dat er iets mis is. Dat is waardevol, maar het voorkomt niets. En een scanner op dezelfde server als een gehackte site kan zelf ook door de inbreker zijn aangepast.
  • Ze vervangen geen updates. Een plugin met een bekend lek blijft lek, ook met een beveiligingsplugin ernaast. Sommige beveiligingsdiensten bieden "virtuele patches" die bekende aanvallen tegenhouden tot je hebt bijgewerkt; handig als overbrugging, niet als vervanging.
  • Ze zijn zelf een plugin. Meer code, meer om bij te werken, soms zelf een lek. En twee beveiligingsplugins tegelijk botsen vaak.
  • Ze kosten rekenkracht, vooral scanners die op je eigen server draaien.

Een redelijke keuze: kijk eerst wat je hoster al doet (firewall, malwarescan, blokkeren van inlogpogingen). Vul aan wat ontbreekt, meestal tweestapsverificatie en het beperken van inlogpogingen. Een uitgebreide beveiligingsplugin is vooral nuttig bij hosting die zelf weinig doet.

Samenvatting

  • Verharden beperkt de schade van een fout of lek; het vervangt updates en wachtwoorden niet.
  • Mappen 755, bestanden 644, wp-config.php strenger; nooit 777.
  • Zet DISALLOW_FILE_EDIT aan, blokkeer PHP in uploads, zet mappenlijsten uit en ruim back-ups, .git en debug.log uit de webmap.
  • Versie verbergen is opruimen, geen beveiliging; beveiligingsheaders helpen de browser je bezoekers te beschermen.
  • Een firewall op de server houdt meer tegen dan een plugin; beveiligingsplugins zijn een aanvulling, geen vervanging.

Quiz

1. Een handleiding zegt: "zet wp-content op 777 als uploaden niet lukt." Wat vind je daarvan?



2. Wat doet DISALLOW_FILE_EDIT?



3. Waarom zit een firewall op de server eerder in de keten dan een firewall in een plugin?



4. Je hebt de generator-tag weggehaald. Is je site nu veilig voor lekken in oude versies?



5. Welke kopregel voorkomt dat een andere site jouw site in een onzichtbaar frame laadt?



Opdracht

Opdracht A7.4: Wat laat je site aan iedereen zien? Vul het adres van je site in. Het programma leest de homepage en de RSS-feed (/feed/) en controleert: staat er geen WordPress-versie in de generator-tag van de HTML en de feed, toont de kopregel X-Powered-By geen PHP-versie, en stuurt je site X-Content-Type-Options: nosniff, een bescherming tegen frames (X-Frame-Options of frame-ancestors) en een Referrer-Policy? HSTS (les 3.1) en Permissions-Policy ontbreken mag (oranje).

Opdracht A7.4: Wat laat je site aan iedereen zien?


Wat je invult en wat we vinden, slaan we niet op. Je browser onthoudt je antwoorden en of je de opdracht hebt gehaald. Ben je aangemeld, dan bewaren we alleen dat je de opdracht (bijna) goed had in Mijn cursussen; daar kun je het ook verwijderen.

Opdracht A7.4b: Geen restjes in de webmap. Bewijs dat het je eigen site is (TXT-record of bestand met de code van de opdracht). Het programma vraagt daarna een korte vaste lijst op: de map /wp-content/uploads/ (geen mappenlijst), /.git/HEAD, /wp-content/debug.log en een paar veelvoorkomende namen van kopieën van wp-config.php. Goed is als geen daarvan inhoud teruggeeft (404 of 403). Het programma probeert niets anders en wijzigt niets.

Opdracht A7.4b: Geen restjes in de webmap

Deze controle vraagt paden op die je alleen bij je eigen site laat nakijken. Klik eerst op "Toon mijn code" en zet die code als TXT-record op _weboke-cursus.<jouw domein> of als bestand op je site (zie de uitleg bij de code).


Wat je invult en wat we vinden, slaan we niet op. Je browser onthoudt je antwoorden en of je de opdracht hebt gehaald. Ben je aangemeld, dan bewaren we alleen dat je de opdracht (bijna) goed had in Mijn cursussen; daar kun je het ook verwijderen.

Verder lezen

Deze artikelen beschrijven de stappen in de panelen van WebOké; in andere panelen werken ze vergelijkbaar.

Even geduld…

Stel je domeinen in

Regel per domein de nameservers, de koppeling aan je hosting en wie de eigenaar wordt.

Je domeinen laden…