Op een maandagochtend kwamen er binnen twintig minuten drie meldingen binnen over gewijzigde bestanden, bij drie sites die verder niets met elkaar te maken hadden. Een fysiotherapiepraktijk, een kleine uitgeverij en een groothandel in verpakkingen. Wat ze wel deelden, bleek een besmette plugin in WordPress te zijn: dezelfde uitbreiding, dezelfde versie, hetzelfde weekend bijgewerkt.
Dit is een geanonimiseerd verslag van dat weekend. Het is opgeschreven omdat het een besmetting betrof die niet via een lek binnenkwam, maar via het kanaal dat wij allemaal vertrouwen: een gewone update.
De melding
Bij de sites die wij beheren, draait een controle die dagelijks vergelijkt of bestanden zijn gewijzigd zonder dat daar een handeling tegenover staat. Zaterdagnacht waren op alle drie de sites bestanden aangepast in dezelfde pluginmap, plus een nieuw bestand in een map waar normaal alleen afbeeldingen staan.
Eén melding is meestal een update die niet netjes is geregistreerd. Drie meldingen op dezelfde map bij niet-verwante sites is iets anders. Dat is het moment waarop je stopt met verklaringen zoeken en begint met isoleren.
De sites zijn diezelfde ochtend in onderhoudsmodus gezet, de betreffende plugin is gedeactiveerd en er is van elke site een volledige kopie veiliggesteld voordat er iets werd aangeraakt. Dat laatste is de stap die achteraf het meeste waard bleek, want zonder die kopieën hadden wij niet kunnen vaststellen wat er precies was toegevoegd.
Wat er in de plugin zat
De plugin was een uitbreiding voor formulieren met enkele tienduizenden installaties. Geen obscuur pakket, maar ook geen huishoudnaam. Hij was enkele maanden eerder overgenomen door een nieuwe eigenaar, iets wat op de pluginpagina alleen te zien was aan een gewijzigde naam bij de ontwikkelaar.
In de nieuwe versie stond code die twee dingen deed. Ze haalde bij elk bezoek van een beheerder een adres op bij een externe server, en ze legde een tweede bestand neer in de uploadmap dat als achterdeur diende. De code was zo geschreven dat hij niets deed bij gewone bezoekers, wat verklaart waarom er niets zichtbaars gebeurde en waarom een oppervlakkige controle niets opleverde.
Dit patroon komt vaker voor dan mensen denken. Een populaire plugin wordt overgenomen, blijft een tijd normaal functioneren en krijgt daarna in een reguliere update iets extra’s mee. De gebruiker doet niets fout: hij klikt op bijwerken, precies zoals hem is aangeraden. Hoe u zo’n overname kunt herkennen, staat bij het signaleren van een plugin die van eigenaar wisselde.
Het herstel per site
Voor alle drie is dezelfde route gevolgd, in ongeveer vier uur per site.
- De plugin volledig verwijderd, inclusief de restanten in de database.
- Het extra bestand in de uploadmap verwijderd en de uploadmap doorgelopen op vergelijkbare bestanden.
- De WordPress-kern en de overige plugins vervangen door verse downloads, om zeker te weten dat er niets was doorgeschreven.
- Alle beheerderswachtwoorden vervangen, de beveiligingssleutels vernieuwd en lopende sessies verbroken.
- Serverlogboeken doorgenomen om te bepalen of de achterdeur ook daadwerkelijk was aangeroepen.
- Een vervangende formulierplugin geïnstalleerd en de bestaande formulieren opnieuw opgebouwd.
Dat laatste punt kostte de meeste tijd, en dat is het onderdeel dat mensen onderschatten. Een formulier overzetten naar een andere plugin betekent velden opnieuw instellen, meldingen opnieuw koppelen en testen of alles aankomt. Bij de groothandel ging het om zeven formulieren, waaronder een offerteaanvraag met vijftien velden.
Wat de logboeken lieten zien
Bij twee van de drie sites was de achterdeur alleen aangemaakt maar nog niet aangeroepen. Bij de derde, de groothandel, stonden er in de nacht van zondag op maandag zeven verzoeken naar dat bestand vanaf twee buitenlandse adressen. Er waren geen wijzigingen doorgevoerd, maar er was wel gekeken.
Dat verschil is precies waarom de snelheid van signaleren zoveel uitmaakt. Achtenveertig uur later hadden alle drie de sites in de tweede fase gezeten, en dan praat je niet meer over een opschoning van vier uur maar over een volledig herstel plus de vraag welke gegevens zijn ingezien.
Voor de groothandel is uit voorzorg wel de afweging gemaakt of er een meldplicht speelde. Omdat er geen aanwijzingen waren dat er gegevens waren opgehaald en er geen wijzigingen zijn aangetroffen, is dat in overleg met hun jurist niet gemeld. Wij zijn geen juristen en die afweging hoort ook niet bij ons te liggen.
Wat wij hieruit hebben meegenomen
Updates zijn geen garantie. Het advies om alles bij te werken blijft staan, want negen van de tien besmettingen komen juist door achterstallige software. Maar bijwerken is niet hetzelfde als veilig zijn, en dat verschil verdient nuance in het gesprek met klanten.
Een paar dagen wachten kost niets. Wij hanteren sindsdien bij niet-kritieke plugins een korte wachttijd na een release, tenzij het om een beveiligingsupdate gaat. Dan zijn de eerste meldingen van anderen al binnen. Voor kritieke sites gebeurt de update eerst op een testomgeving; hoe zo’n opzet werkt, staat bij het werken met een aparte testomgeving.
Signalering is de kern. Zonder dagelijkse vergelijking van bestanden hadden deze drie sites maanden zo kunnen draaien. Er was niets kapot, niets traag en niets zichtbaars. Dat is bij deze categorie precies de bedoeling van de aanvaller.
Minder plugins is minder blootstelling. Bij de uitgeverij bleek de betreffende plugin voor één formulier te worden gebruikt dat ook met hun bestaande pakket kon. Twee jaar lang een extra pakket meedragen voor iets wat er al was.
Deze manier van werken, met controle op wijzigingen en een bewuste volgorde bij updates, is waar doorlopende bewaking en bescherming van WordPress-sites in de praktijk uit bestaat. Niet spannend, wel het verschil tussen vier uur en vier dagen.
Concrete volgende stap: kijk in uw pluginlijst naar de vijf uitbreidingen die u het langst heeft en zoek op wanneer ze voor het laatst zijn bijgewerkt en door wie. Ziet u een ontwikkelaarsnaam die u niet herkent, dan is dat het gesprek van deze week.



