Module 7 · 7.4
Nederlands
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:
| Wat | Rechten | Betekenis |
|---|---|---|
| Mappen | 755 | Eigenaar mag alles, anderen mogen lezen en openen |
| Bestanden | 644 | Eigenaar mag lezen en schrijven, anderen alleen lezen |
| wp-config.php | strenger, bijvoorbeeld 600 of 640 | Alleen 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 -IndexesVeel 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.gzofdatabase.sqlin 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.phpmetphpinfo().
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:
| Kopregel | Wat hij doet |
|---|---|
Strict-Transport-Security | Alleen nog via https (les 3.1) |
X-Content-Type-Options: nosniff | De 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-origin | Bij een klik naar een andere site gaat alleen je domeinnaam mee, niet het volledige adres |
Permissions-Policy | Zet browserfuncties uit die je site niet gebruikt (camera, microfoon, locatie) |
Content-Security-Policy | Bepaalt 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
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.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.
Verder lezen
Deze artikelen beschrijven de stappen in de panelen van WebOké; in andere panelen werken ze vergelijkbaar.
- DirectAdmin handleiding 11.5: Rechten van bestanden en mappen (chmod)
- DirectAdmin handleiding 11.4: Verborgen bestanden zoals .htaccess tonen en bewerken
- DirectAdmin handleiding 15.10: Web Applicatie Firewall
- DirectAdmin handleiding 15.11: Imunify360: je website scannen op malware
- Bestanden blokkeren via .htaccess
- PHP-beveiliging: uitgeschakelde functies
- WordPress verharden (developer.wordpress.org, Engels): https://developer.wordpress.org/advanced-administration/security/hardening/
- Beveiligingsheaders (MDN, Engels): https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#security
