Kennisbank · Webdevelopment
Hoe beveilig je een WordPress website?

Een WordPress-site beveiligen komt neer op vijf dingen: alles bijgewerkt houden, inloggen met een uniek wachtwoord en tweestapsverificatie, plugins en thema's weggooien die je niet gebruikt, back-ups maken die je een keer hebt teruggezet, en hosting die de basis voor je regelt. Bij vrijwel elke gehackte site die ik onder ogen krijg ontbrak een van die vijf.
Hieronder staat per onderdeel hoe het werkt, wat er in de praktijk misgaat en waaraan je dat merkt. Inclusief het stuk waar bijna niemand aan denkt: de melding bij de Autoriteit Persoonsgegevens als er persoonsgegevens bij betrokken zijn.
Waarom een WordPress-site wordt aangevallen
Het misverstand dat ik het vaakst hoor: mijn site is te klein om interessant te zijn. Zo werkt het niet. Geen enkele aanval op een gewone bedrijfswebsite is de keuze van een mens die jouw bedrijf heeft uitgezocht.
Zodra een lek in een plugin openbaar wordt, gaan er scanners rond die het hele internet aflopen en overal proberen of dat lek erin zit. Die kijken niet naar je omzet of je branche, maar of het antwoord van je server verraadt dat plugin X versie Y erop staat. Een lek in een plugin met miljoenen installaties is voor een aanvaller meer waard dan een lek in de kern van WordPress.
Wat er met een gekaapte site gebeurt
Je site wordt zelden gesloopt, want slopen levert niets op. Wat wel oplevert: honderden verborgen pagina's over medicijnen of gokken die naar de sites van de aanvaller linken, doorverwijzingen die alleen bezoekers uit Google te zien krijgen, een nagemaakte inlogpagina van een bank in een map onder jouw domein, spam die via jouw server de deur uit gaat, en klantgegevens die worden meegenomen.
De besmetting komt bijna altijd langs drie routes binnen: een verouderde plugin of thema, een wachtwoord dat te raden of elders gelekt is, of software van een louche downloadsite. Dat laatste zie ik nog steeds: een betaald thema dat ergens gratis rondzwerft, met een extra bestand erin dat er niet hoort.
Updates zijn de belangrijkste maatregel
Als je maar één ding doet, doe dan dit. Bijna elke inbraak gebruikt een lek waarvoor allang een oplossing bestond. Het gat zat niet in de software, het zat in de maanden tussen de oplossing en het moment dat jij hem installeerde.
WordPress installeert kleine onderhouds- en beveiligingsversies sinds versie 3.7 uit oktober 2013 vanzelf. Daar hoef je niets voor te doen. Het misgaat bij de plugins en het thema, want dat is de kant waar de meeste lekken zitten en waar jij aan zet bent. Sinds WordPress 5.5 van augustus 2020 kun je per plugin automatische updates aanzetten, met een schakelaar in de rechterkolom van je pluginlijst.
Voor een eenvoudige brochuresite zet ik die schakelaar overal aan. Het risico dat een update iets kapotmaakt weegt niet op tegen het risico dat je maandenlang op een lek blijft zitten. Bij een webshop of maatwerk wil je een testomgeving en een back-up vooraf. Draai je dat niet, zet ze dan in elk geval aan voor alles wat met beveiliging of betalingen te maken heeft.
Verlaten plugins herkennen
Een plugin die niemand meer onderhoudt is gevaarlijker dan een plugin met een bekend lek, want bij die laatste komt er nog een oplossing. WordPress geeft je geen enkel signaal als de maker ermee stopt.
Kijk op de pagina van de plugin in de WordPress-map naar drie dingen: wanneer hij voor het laatst is bijgewerkt, tot welke WordPress-versie hij is getest, en of er nog vragen worden beantwoord op het forum. De melding dat een plugin niet is getest met de laatste drie hoofdversies is het eerste alarmsignaal.
Erger is de plugin die is gesloten. WordPress.org haalt plugins uit de map als er een beveiligingsprobleem is dat niet wordt opgelost. De plugin blijft dan gewoon op jouw site staan en werken, zonder update en zonder waarschuwing. Let ook op een populaire plugin die van eigenaar wisselt. Dat gebeurt regelmatig, en soms verschijnt er daarna reclame, een verzamelaar van gegevens of gewoon niets meer.
De remedie is saai en hij werkt. Eén keer per kwartaal je lijst doorlopen en alles weggooien wat je niet gebruikt. Uitgeschakeld is niet weg, de bestanden staan er nog en zijn nog steeds bereikbaar.
Inloggen, tweestapsverificatie en rollen
Een lek moet een aanvaller vinden. Een zwak wachtwoord kan hij gewoon raden.
Gebruik voor elke site een uniek wachtwoord uit een wachtwoordbeheerder. Hergebruik is de reden dat aanvallen slagen zonder dat er ergens een lek zat: een lijst met gelekte combinaties van een heel andere dienst wordt op jouw inlogpagina uitgeprobeerd, en soms zit die van jou erbij.
Zet daarnaast tweestapsverificatie aan voor iedereen die kan inloggen. WordPress heeft dat niet ingebouwd, dus daar is een plugin voor nodig. De gangbare vorm is een code uit een authenticatie-app die elke dertig seconden verandert. Bewaar de herstelcodes buiten je telefoon, anders sluit je jezelf buiten als dat toestel kwijtraakt.
Wie mag wat
WordPress kent vijf rollen: beheerder, redacteur, auteur, medewerker en abonnee. Het verschil dat ertoe doet is dat alleen een beheerder plugins mag installeren, en wie plugins mag installeren mag code op je server draaien. Een beheerdersaccount is dus geen inlog maar volledige toegang.
Geef iedereen de laagste rol waarmee hij zijn werk kan doen en loop je gebruikerslijst één keer per jaar na. Voor koppelingen met andere software gebruik je een toepassingswachtwoord, sinds WordPress 5.6 ingebouwd in je profiel. Dat kun je per koppeling intrekken zonder je eigen wachtwoord te wijzigen.
De twee deuren: wp-login.php en xmlrpc.php
Elke WordPress-site heeft twee adressen waarop je kunt inloggen. De inlogpagina die je kent, en een bestand dat xmlrpc.php heet en waar bijna niemand van weet.
Op de inlogpagina komen dagelijks geautomatiseerde pogingen binnen. Dat hoort erbij. Vervelend wordt het als er zoveel tegelijk komen dat je server het niet bijhoudt, want dan gaat je site plat zonder dat er iemand binnen is. Beperk het aantal mislukte pogingen per adres en zet er eventueel een CAPTCHA voor.
Xmlrpc.php is de oude manier waarop programma's van buitenaf met WordPress praten. Sinds WordPress 4.7 uit december 2016 loopt dat verkeer via de REST API en gebruiken de meeste apps die. Het oude bestand staat er standaard nog. Er zit een methode in waarmee je in één verzoek honderden wachtwoorden kunt proberen, wat het tellen van mislukte pogingen omzeilt, en de pingbackfunctie laat jouw server meedoen aan een aanval op iemand anders.
Zet je het uit, doe dat dan op serverniveau of in je firewall. Het filter binnen WordPress schakelt alleen de methodes uit die inloggen vereisen; het bestand blijft antwoorden. Controleer eerst in je logboek of er nog iets legitiems langskomt.
Bestandsrechten en het configuratiebestand
Bestandsrechten bepalen wie een bestand mag lezen, wijzigen en uitvoeren. De gangbare instelling is 755 voor mappen en 644 voor bestanden. Het configuratiebestand wp-config.php mag strenger, op 640 of 600.
De waarde waar je nooit op uitkomt is 777. Die betekent dat iedereen op de server mag schrijven, en je ziet hem opduiken omdat een handleiding hem adviseert als een upload niet lukt. Lukt schrijven niet, dan ligt het aan de eigenaar van het bestand en dat lost je hoster op.
In wp-config.php staan je databasegegevens en acht sleutels die je aanmeldsessies beveiligen. Vermoed je dat er iemand binnen is geweest, vervang die sleutels dan. Iedereen wordt uitgelogd, de indringer ook. Met de regel DISALLOW_FILE_EDIT haal je bovendien de bestandsbewerker uit het beheerscherm, zodat iemand die binnenkomt niet meteen code kan aanpassen.
Laat tot slot geen PHP uitvoeren in je uploadmap. Dat is de map waar van buitenaf bestanden in belanden, dus daar hoort niets te draaien. Een goede hoster regelt dat. Wil je weten wat er verder op die serverkant gebeurt, kijk dan bij back-end ontwikkeling.
De PHP-versie waarop je site draait
WordPress draait op PHP, en die taal heeft zijn eigen levensduur. Elke versie krijgt ongeveer twee jaar volledige ondersteuning en daarna nog een jaar alleen beveiligingsoplossingen. Daarna komt er niets meer, ook niet bij een ernstig lek.
PHP 7.4 kreeg na november 2022 geen beveiligingsupdates meer, PHP 8.0 stopte in november 2023 en PHP 8.1 eind 2025. Draai je nog op zo'n versie, dan ligt er onder je site een laag die niemand meer repareert.
Je versie staat in het beheerscherm onder Gereedschap en dan Sitediagnose, het onderdeel dat sinds WordPress 5.2 uit mei 2019 meekomt. Overstappen doe je bij je hoster, meestal met een keuzelijst in het bedieningspaneel. Wat er mis kan gaan is een oude plugin die code gebruikt die uit nieuwere PHP-versies is verdwenen, dus test eerst op een kopie. Loopt het vast, dan weet je meteen welk onderdeel al jaren niet is aangeraakt. Hoe die versies zich tot elkaar verhouden, leg ik uit bij PHP.
Back-ups die je ook echt kunt terugzetten
Een back-up die je nooit hebt teruggezet is geen back-up, het is een aanname. Hier zie ik de meeste onaangename verrassingen.
Wat erin moet: de database, de map wp-content met je uploads, thema's en plugins, en het configuratiebestand. Alleen de database is niet genoeg, want dan mis je je afbeeldingen. Alleen de bestanden ook niet, want dan mis je je teksten en je bestellingen.
Hoe vaak hangt af van hoe snel je site verandert. Bij een blog per maand is dagelijks ruim voldoende, bij een webshop is elk uur zonder back-up een uur aan bestellingen dat je kunt kwijtraken. Bewaar de kopieën niet op dezelfde server: een back-up in een map onder je eigen site verdwijnt samen met de site, en komt soms via Google in de zoekresultaten terecht.
Let op de bewaartermijn. Een besmetting wordt vaak weken later ontdekt, dus met zeven dagen aan back-ups heb je alleen kopieën waar de rommel al in zit. Dertig dagen is een redelijk minimum. Zet er daarna één keer echt een terug op een testomgeving. Dat je gegevens na een incident tijdig kunt herstellen staat letterlijk in artikel 32 van de AVG, dus het is een verplichting zodra je persoonsgegevens verwerkt.
Beveiligingsplugins: wat ze wel en niet doen
Wordfence, Solid Security en Sucuri zijn de bekendste. Solid Security heette tot een paar jaar geleden iThemes Security, dus oudere handleidingen noemen die naam nog.
Wat ze goed doen: mislukte inlogpogingen tellen en blokkeren, tweestapsverificatie toevoegen, je bestanden vergelijken met de originelen uit de WordPress-map, en je waarschuwen als er een beheerder bijkomt of een bestand verandert. Die meldingen zijn de meeste waarde van zo'n plugin.
Wat ze minder goed doen dan de reclame suggereert. Een firewall die als plugin draait, ziet een verzoek pas als PHP al is gestart. Bij de gratis versie van Wordfence lopen de firewallregels bovendien dertig dagen achter op de betaalde versie, precies de periode waarin een vers lek het meest wordt misbruikt. Een firewall vóór je site, zoals die van Cloudflare, houdt verkeer tegen voordat het je server bereikt.
Een scanner vindt verder alleen wat hij herkent, en code die speciaal voor jouw site is versleuteld glipt erlangs. Is een aanvaller eenmaal beheerder, dan zet hij je beveiligingsplugin gewoon uit. Installeer er daarom één en geen drie, want firewalls naast elkaar botsen en geven elkaar de schuld.
Hosting en https
Een deel van je beveiliging koop je in bij je hoster, of je dat nu weet of niet. Houdt hij PHP en de serversoftware bij? Staan de sites van verschillende klanten van elkaar gescheiden? Draaien er back-ups die je zelf kunt terugzetten, en krijg je iemand te spreken als het misgaat?
Bij goedkope gedeelde hosting zonder scheiding kan een besmetting op de site van de buurman naar jouw map overspringen. Dat is de reden dat ik hosting waar je niets over kunt vragen geen besparing vind. Waar je nog meer op let bij het kiezen van een partij, lees je bij webhosting.
Https hoort er standaard op te zitten. Let's Encrypt levert sinds 2016 gratis certificaten die negentig dagen geldig zijn en zichzelf vernieuwen, en Chrome zet sinds 2018 bij elke pagina zonder https het label "niet veilig" in de adresbalk.
Wel graag met de juiste verwachting. Https versleutelt het verkeer tussen bezoeker en server, zodat niemand op het wifinetwerk in de trein kan meelezen. Over de veiligheid van je site zelf zegt het niets. Een gehackte site met een geldig certificaat is nog steeds een gehackte site. Wat zo'n certificaat nu eigenlijk is, behandel ik bij SSL-certificaten.
Waaraan je ziet dat een site gehackt is
Meestal ziet je site er gewoon uit. Dat is het lastige eraan.
Het eerste signaal is vaak Google: een melding over beveiligingsproblemen in Search Console, of bezoekers die een rood waarschuwingsscherm van hun browser krijgen. Vanaf dat moment ben je je verkeer kwijt tot het is opgelost. Zoek zelf eens op site: gevolgd door je domein en tel of het aantal resultaten klopt. Onbekende pagina's, vaak met Japanse of Russische tekens in de titel, verschijnen daar het eerst.
Verder zijn er de kleinere signalen. Een beheerder in je gebruikerslijst die je niet kent, een site die ineens veel trager is, een hoster die mailt over hoog verbruik, of je eigen offertes die niet meer aankomen omdat je server op een zwarte lijst staat. Ook bestanden met vreemde namen in je hoofdmap, met een wijzigingsdatum van vannacht terwijl er niemand heeft gewerkt.
Kijk bij twijfel in de map wp-content/mu-plugins. Wat daarin staat wordt automatisch geladen en verschijnt niet in je gewone pluginlijst. Het is een geliefde schuilplaats.
Wat je doet als je site gehackt is
Werk in deze volgorde en sla niets over.
Zet de site offline of in onderhoudsmodus, zodat bezoekers geen schade oplopen. Maak een kopie van de besmette site voordat je iets weggooit, want die heb je nodig om te achterhalen hoe het is gebeurd. Verander daarna alle wachtwoorden: WordPress, hostingaccount, database, FTP en het e-mailadres van de beheerder. Vervang ook de sleutels in wp-config.php en gooi de gebruikers eruit die er niet horen.
Zet vervolgens een back-up terug van vóór de besmetting en werk meteen alles bij voordat je weer online gaat. Anders sta je binnen een dag op hetzelfde punt. Heb je geen schone back-up, dan vervang je de kern, alle thema's en alle plugins door verse downloads, en houd je alleen je uploads en de database over. Die twee moet je met de hand nalopen.
Zoek daarna uit hoe het kon, want zonder dat antwoord herhaalt het zich. Kijk in de toegangslogboeken rond de datum van het eerste vreemde bestand. Vraag in Search Console een herbeoordeling aan als Google je had gemarkeerd, en kijk een week later opnieuw. Achtergebleven achterdeurtjes komen vaak pas dan boven, meestal via een geplande taak die zichzelf opnieuw installeert.
Een datalek melden binnen 72 uur
Dit onderdeel wordt bij een hack het vaakst vergeten. Zijn er persoonsgegevens ingezien, of konden ze worden ingezien, dan heb je een datalek in de zin van de AVG, die sinds 25 mei 2018 geldt. In Nederland bestond zo'n meldplicht al sinds 1 januari 2016.
Artikel 33 zegt dat je een datalek binnen 72 uur na ontdekking meldt bij de Autoriteit Persoonsgegevens, tenzij het onwaarschijnlijk is dat er risico voor de betrokken personen uit voortkomt. Die 72 uur loopt door in het weekend. Weet je nog niet alles, dan meld je wat je hebt en vul je later aan. Loopt er een hoog risico voor de mensen zelf, dan moet je hen ook informeren, in gewone taal. Dat staat in artikel 34.
Wat als persoonsgegevens telt is ruimer dan mensen denken. Bestellingen met adressen, inzendingen van je contactformulier die in de database blijven staan, een ledenlijst, een verzameling e-mailadressen. Een brochuresite zonder formulier en zonder accounts is een van de weinige gevallen waarin er echt niets te lekken valt.
Regel daarom nu twee dingen. Zorg voor een verwerkersovereenkomst met je hoster, want die verwerkt namens jou. En houd een intern register bij van alle datalekken, ook die je niet meldt. Dat register is verplicht en vier kolommen volstaan: wat er gebeurde, wanneer je het ontdekte, wat je hebt gedaan en of je hebt gemeld.
Wat overdreven is, en welk ritme je volhoudt
Niet alles wat als beveiliging wordt verkocht is de moeite waard op een site van tien pagina's. De databaseprefix veranderen op een bestaande site staat in elke oude handleiding, levert vrijwel niets op en de kans dat je onderweg iets breekt is reëel. Bij een nieuwe installatie kost het niets, dus doe het dan.
De inlogpagina verhuizen naar een ander adres ruimt je logboek op en houdt de domste scanners tegen. Als beveiliging telt het niet, want wie binnen wil komen vindt hem alsnog. Een pentest voor een brochuresite is weggegooid geld, en firewallregels overnemen uit een blog uit 2014 eindigt met een formulier dat niemand meer kan versturen.
Wat wel loont is een klein ritme dat je volhoudt. Elke maand updates draaien, kijken of de back-up van vannacht er staat en de meldingen van je beveiligingsplugin doorlezen in plaats van wegklikken. Elk kwartaal je pluginlijst opschonen en je gebruikers nalopen. Elk jaar een back-up echt terugzetten en je PHP-versie controleren.
Dat kost je bij elkaar een paar uur per jaar. Minder dan één avond zoeken naar wat er in je uploadmap is komen wonen.
Veelgestelde vragen over WordPress beveiligen
Is WordPress onveilig?
Nee. De kern wordt door een groot team onderhouden en problemen worden er snel uit gehaald. Het overgrote deel van de inbraken komt binnen via plugins en thema's van derden of via zwakke wachtwoorden. Dat WordPress vaak in het nieuws komt, komt door het aantal sites dat erop draait.
Hoe weet ik of mijn WordPress-site is gehackt?
Zoek in Google op site: gevolgd door je domein en kijk of er pagina's tussen staan die je niet kent. Controleer daarna je gebruikerslijst op onbekende beheerders en kijk in Search Console bij Beveiligingsproblemen. Zeggen bezoekers dat ze worden doorgestuurd terwijl jij niets ziet, dan is dat vrijwel altijd raak, want zo'n doorverwijzing wordt alleen getoond aan bezoekers die uit Google komen.
Heb ik een beveiligingsplugin nodig?
Eén is verstandig, vooral vanwege de meldingen. Een plugin die waarschuwt als er een beheerder bijkomt of een kernbestand verandert geeft je de kans er vroeg bij te zijn. Installeer er niet meer dan één en zie het niet als vervanging voor updates: de plugin repareert het lek niet.
Moet ik automatische updates aanzetten?
Voor een gewone bedrijfswebsite zonder maatwerk wel. De kans dat een update iets stukmaakt is kleiner dan de kans dat je maandenlang op een bekend lek blijft zitten. Heb je een webshop of maatwerkfuncties, zet ze dan aan voor beveiligingsgevoelige plugins en werk de rest met de hand bij, na een back-up.
Wat doe ik met een plugin die niet meer wordt bijgewerkt?
Zoek een vervanger die wel wordt onderhouden, of gooi hem weg als je de functie kunt missen. Moet je hem echt houden, laat dan iemand naar de code kijken. Een verlaten plugin met een formulier of een uploadfunctie erin is het risico bijna nooit waard.
Is het verstandig om xmlrpc.php uit te zetten?
Op de meeste sites wel. Het verkeer dat er vroeger langsging loopt tegenwoordig via de REST API, en het bestand wordt vooral gebruikt om wachtwoorden te raden en aanvallen op anderen te weerkaatsen. Controleer eerst je serverlogboek op legitiem gebruik en blokkeer daarna op serverniveau, want een filter binnen WordPress laat het bestand nog antwoorden.
Hoe vaak moet ik een back-up maken?
Zo vaak als je het verlies van de tussenliggende periode kunt dragen. Voor een site die je maandelijks bijwerkt is dagelijks ruim voldoende, voor een webshop wil je meerdere keren per dag. Belangrijker dan de frequentie zijn de bewaartermijn en de plek: minstens dertig dagen, en niet op de server waar je site draait.
Kan ik een gehackte site zelf opschonen?
Met een schone back-up van vóór de besmetting wel: terugzetten, meteen alles bijwerken en alle wachtwoorden plus de sleutels in wp-config.php vervangen. Zonder die back-up wordt het handwerk, en dat is het moment waarop hulp inschakelen goedkoper is dan doorploeteren. Eén gemiste achterdeur betekent dat je over twee weken opnieuw begint.
Moet ik een datalek melden als mijn website is gehackt?
Waren er persoonsgegevens toegankelijk, dan meld je het binnen 72 uur na ontdekking bij de Autoriteit Persoonsgegevens, tenzij het onwaarschijnlijk is dat het risico oplevert voor de betrokken personen. Bij een hoog risico moet je die mensen zelf ook informeren. Ook een lek dat je niet meldt leg je intern vast, want dat register is verplicht.
Welke PHP-versie moet ik draaien?
Een versie die nog beveiligingsupdates krijgt. Voor 7.4 hielden die op in november 2022, voor 8.0 een jaar later, en voor 8.1 aan het eind van 2025. Je huidige versie vind je in het beheerscherm bij de sitediagnose. Gebruik je oude plugins, test de overstap dan eerst op een kopie.
Waarom krijg ik zoveel mislukte inlogpogingen te zien?
Omdat je site wordt afgelopen door programma's die overal dezelfde lijst met gebruikersnamen en wachtwoorden proberen. Dat gebeurt bij vrijwel elke WordPress-site en betekent niet dat iemand het op jou heeft gemunt. Met een uniek wachtwoord en tweestapsverificatie is het vooral ruis. Wordt je site er traag van, dan is blokkeren vóór je server de oplossing.
Beschermt mijn hoster mij tegen hacks?
Gedeeltelijk. Een goede hoster houdt de server bij, scheidt klanten van elkaar, draait back-ups en blokkeert een deel van het kwaadaardige verkeer voordat het bij je site komt. Je plugins, je thema en je wachtwoorden blijven jouw verantwoordelijkheid, ook bij beheerde WordPress-hosting. Vraag na wat er precies in het pakket zit, want dat verschilt sterk.
Is een site op WordPress.com veiliger dan een eigen installatie?
Op WordPress.com wordt het onderhoud van software en server voor je gedaan, met minder vrijheid in plugins als prijs. Bij een eigen installatie heb je alle vrijheid en alle verantwoordelijkheid. Het verschil zet ik op een rij bij WordPress.com tegenover WordPress.org.
Wat doe ik tegen spam in mijn reacties?
Reactiespam is hinderlijk maar zelden een inbraakroute. Zet reacties uit als je ze niet gebruikt, en gebruik anders een spamfilter met handmatige goedkeuring voor de eerste reactie van iemand. De rest daarover vind je bij comment spam.
Dit artikel hoort bij Webdevelopment. Daar vind je meer uitleg over hetzelfde onderwerp.
