Een technische groothandel uit het oosten van het land meldde zich met een klacht die we vaker horen: de website was traag geworden en niemand wist waarom. Er was niets veranderd, er waren geen nieuwe plugins bijgekomen en het bezoek was gelijk gebleven. Wat er wel gebeurde, bleek een cryptominer op de website te zijn: code die de rekenkracht van hun server gebruikte om digitale munten te delven voor iemand anders.

Dit is een geanonimiseerd verslag van dat traject, met de cijfers zoals ze in de rapportage stonden. Niet omdat het spectaculair was, maar juist omdat het zo onopvallend verliep dat het maanden kon doorgaan.

De klacht zoals hij binnenkwam

De ondernemer beschreef het als volgt: het beheerscherm voelde stroperig, het opslaan van een productpagina duurde soms twintig seconden, en een paar keer per dag kregen bezoekers een foutmelding over een overbelaste server. Zijn hostingpartij had gemeld dat hij structureel over zijn processorlimiet ging en had voorgesteld om een zwaarder pakket af te nemen, ruim tweehonderd euro per jaar duurder.

Dat is de gebruikelijke route, en in veel gevallen is het ook terecht. Hier klopte het verhaal alleen niet. Een site met ongeveer negenhonderd producten en zo’n vierhonderd bezoekers per dag hoort op een normaal pakket comfortabel te draaien. Een verdubbeling van de capaciteit vragen zonder dat er iets is gegroeid, is een aanwijzing dat er iets anders speelt.

Wat de meting liet zien

De eerste stap was niet zoeken naar malware maar simpelweg meten wanneer de belasting optrad. Uit de serverstatistieken kwam een patroon dat meteen opviel: de processorbelasting stond ook ‘s nachts op zeventig tot negentig procent, terwijl er tussen twee en zes uur ‘s nachts vrijwel geen bezoekers waren.

Dat sluit de meeste onschuldige verklaringen uit. Zware pagina’s, een slecht cachebeleid of een logge plugin geven pieken die het bezoekpatroon volgen. Belasting die dag en nacht gelijk blijft, hoort bij een proces dat uit zichzelf draait.

Ook opvallend: de site zelf was niet langzaam in de zin van veel laadtijd per pagina. De server was gewoon bezet. Dat verschil is belangrijk, want het is precies waarom een gewone snelheidstest hier weinig oplevert. De meetwaarden zagen er redelijk uit; het gedrag onder belasting niet.

Waar de code stond

Een scan op bestandsniveau vond twee dingen. In de map van een verlopen premium-plugin, die nog wel actief was, stond een bestand met een naam die op een systeembestand leek. Daarin zat sterk versleutelde code die bij elke pagina-aanroep werd meegestart.

Daarnaast stond er in de uploadmap een klein bestand dat als achterdeur diende. Daarmee kon de aanvaller op elk moment nieuwe opdrachten binnenhalen, ook als het eerste bestand zou worden verwijderd. Die combinatie is standaard: één component doet het werk, één component zorgt dat het terugkomt.

De miner draaide niet in de browser van bezoekers, wat een tijd geleden vaker voorkwam, maar op de server zelf. Dat is voor de eigenaar vervelender, omdat u de rekening voor de rekenkracht betaalt terwijl niemand het merkt.

Hoe het binnen was gekomen

De ingang bleek de verlopen plugin. De licentie was ruim een jaar eerder niet verlengd, waardoor er geen updates meer binnenkwamen. In die periode was er een kwetsbaarheid in die plugin gepubliceerd. Vanaf dat moment is het een kwestie van weken voordat geautomatiseerde scanners langskomen.

Dat is een pijnlijk detail, want de licentie kostte destijds negenenveertig euro per jaar. Het niet verlengen daarvan heeft uiteindelijk een veelvoud gekost. Het is ook de reden dat wij licentiebeheer als saai maar noodzakelijk onderdeel zien; wat daarbij komt kijken staat in het artikel over het beheren van pluginlicenties.

Uit de logbestanden bleek dat de eerste verdachte aanroep ongeveer vijf maanden voor de melding had plaatsgevonden. In die vijf maanden was er niets kapotgegaan, niets gewijzigd aan de zichtbare site en geen enkele melding verstuurd. Precies dat maakt deze categorie zo lastig te betrappen.

Het herstel

Het traject besloeg ruim twee werkdagen en verliep in deze volgorde.

  1. Site tijdelijk in onderhoudsmodus en een volledige kopie van bestanden en database veiliggesteld voor onderzoek.
  2. Kern, thema en alle plugins vervangen door verse downloads. De verlopen plugin is niet teruggeplaatst maar vervangen door een onderhouden alternatief.
  3. De uploadmap doorgelopen op bestanden die daar niet horen, en het uitvoeren van code in die map geblokkeerd.
  4. Alle wachtwoorden vernieuwd: beheerders, database, FTP en hostingpaneel. Sessies verbroken.
  5. De beveiligingssleutels in het configuratiebestand vervangen, zodat oude cookies ongeldig werden.
  6. Twee weken lang dagelijks de processorbelasting gecontroleerd om te zien of de nachtelijke piek echt weg was.

Na de eerste nacht stond de nachtelijke belasting op vier procent. Het beheerscherm reageerde weer normaal en het zwaardere hostingpakket bleek onnodig. De ondernemer heeft dat aanbod ingetrokken.

Wat deze zaak leert

Drie dingen die wij hieruit meenemen en die breder gelden.

Traagheid is een symptoom, geen diagnose. Wordt een site langzamer zonder aanwijsbare oorzaak, kijk dan eerst naar het patroon van de belasting voordat u meer capaciteit koopt. Belasting buiten kantooruren zonder bezoekers is een rood signaal.

Een verlopen licentie is een beveiligingsprobleem, geen administratief detail. Zolang de plugin actief blijft maar geen updates meer krijgt, wordt hij met de maand risicovoller. Een plugin die u niet meer bijhoudt, hoort weg; hoe u zoiets herkent staat bij het herkennen van plugins zonder onderhoud.

Geen zichtbare schade betekent niet dat er niets aan de hand is. Deze site is nooit beklad, er is geen data gestolen voor zover te achterhalen, en er stond geen spam op. Toch draaide er vijf maanden lang code van een vreemde op de server, met alle mogelijkheden die daarbij horen.

Structurele bewaking van serverbelasting en gewijzigde bestanden hoort daarom bij het doorlopend afschermen en bewaken van een WordPress-site. Dat is precies het soort werk dat pas opvalt als het er niet is.

Concrete volgende stap: vraag bij uw hosting het verbruiksoverzicht van de afgelopen maand op en kijk naar de nachtelijke uren. Staat daar een vlakke lijn op hoog niveau in plaats van een dal, dan is dat het gesprek dat u deze week voert.