Op een dinsdagavond in maart kregen wij een bericht via WhatsApp van de eigenaar van een webshop in kampeer- en outdoorartikelen, ergens in Gelderland. Twee klanten hadden diezelfde dag gebeld met hetzelfde verhaal: na het klikken op de afrekenknop kwamen ze op een vreemde pagina terecht die om hun kaartgegevens vroeg. De shop zelf werkte gewoon, de bestellingen kwamen binnen, en op zijn eigen laptop zag hij niets vreemds.
Dat is het lastige aan een gehackte webshop: de aanvaller heeft er belang bij dat de eigenaar niets merkt. Deze case beschrijft hoe het onderzoek verliep, wat wij aantroffen, hoe het herstel eruitzag en wat de ondernemer er achteraf van heeft geleerd. De naam van het bedrijf laten wij weg; de details zijn verder ongewijzigd.
De situatie bij binnenkomst
De shop draaide op WooCommerce, ongeveer negenhonderd producten, iDEAL via een betaaldienstverlener, koppeling met een verzendpartij en een boekhoudpakket. Ruim dertig plugins. Er was ooit een bureau geweest dat de site had gebouwd, maar dat contact was twee jaar geleden verwaterd. Sindsdien deed de eigenaar de updates zelf, “als er tijd voor was”.
De eerste vraag was of het probleem reproduceerbaar was. Op een gewone browser op een desktop gebeurde er niets bijzonders. Op een telefoon, via een zoekopdracht in Google en met de winkelwagen gevuld, wél. De code was zo geschreven dat hij alleen actief werd bij bezoekers die aan drie voorwaarden voldeden: mobiel, afkomstig van een zoekmachine, en niet ingelogd. Precies de groep die de eigenaar zelf nooit vormt.
De tweede vraag: sinds wanneer? De verkoopcijfers gaven het antwoord. Het aantal bestellingen was al negentien dagen ongeveer een kwart lager dan normaal, terwijl het bezoekersaantal gelijk was gebleven. Dat was opgevallen, maar toegeschreven aan het seizoen.
Het onderzoek
Wij begonnen met wat wij altijd eerst doen: een volledige kopie maken van de site en de database in de staat waarin hij op dat moment verkeerde. Niet om terug te zetten, maar om te kunnen onderzoeken zonder bewijs te vernietigen. Daarna gingen wij op vier plekken kijken.
De bestanden. Door de WordPress-kernbestanden en de plugins te vergelijken met de originele versies van de makers, vielen drie afwijkingen op: een gewijzigd bestand in een plugin voor productfilters, een bestand in de uploadsmap dat op een afbeelding leek maar PHP-code bevatte, en een extra bestand in de themamap.
De database. In de tabel met opties stond een lang, gecodeerd stuk tekst dat bij elke paginaweergave werd uitgevoerd. Dat was de eigenlijke omleiding. Het bestand in de uploadsmap diende om die tekst opnieuw te plaatsen als iemand hem verwijderde.
De gebruikers. Er stond één extra beheerdersaccount, aangemaakt op de vierde dag, met een e-mailadres op een domein dat nergens op sloeg.
De logboeken. De toegangslogs van de hostingpartij lieten zien welk verzoek als eerste een reactie had opgeleverd die niet klopte. Dat verzoek ging naar de plugin voor productfilters, een versie die vier maanden eerder een beveiligingsupdate had gekregen. Die update was nooit uitgevoerd.
Het herstel
Om 22:15 die avond lag het plan er. Het werk liep die nacht door, met het technische team dat op afstand werkt; om 08:00 de volgende ochtend was de shop schoon en draaide alles weer.
- De shop in onderhoudsmodus voor bezoekers vanaf zoekmachines, zodat er geen klanten meer in de val liepen, terwijl bestaande klanten wel konden afrekenen.
- Kernbestanden, thema en alle plugins vervangen door originele versies. Waar maatwerk zat, is dat regel voor regel vergeleken voordat het terugkwam.
- De uploadsmap uitgekamd op bestanden met een PHP-extensie of PHP-inhoud, en uitvoering van PHP in die map geblokkeerd.
- De database schoongemaakt: de geïnjecteerde optie verwijderd, het onbekende beheerdersaccount opgeheven, de bestellingen gecontroleerd op vreemde regels.
- Alles vernieuwd wat een sleutel is: wachtwoorden van alle beheerders, het databasewachtwoord, de FTP-gegevens, de API-sleutels van de betaaldienst en de verzendpartij, en de beveiligingssleutels in wp-config.php, waardoor alle openstaande sessies vervielen.
- Het gat gedicht: de kwetsbare plugin bijgewerkt, en drie plugins die al een jaar niet meer werden onderhouden vervangen of verwijderd.
- Een firewall ervoor gezet en tweestapsverificatie ingeschakeld op de beheerdersaccounts.
- Herbeoordeling aangevraagd bij Google, met een korte beschrijving van wat er was gebeurd en wat er was hersteld.
Wat wij bewust níét deden: een oude back-up terugzetten. De laatste schone back-up was van vóór de besmetting, maar daar zaten negentien dagen aan bestellingen, klantaccounts en voorraadmutaties tussen. Bij een webshop weegt dat zwaar. Waarom die afweging bij een shop anders uitpakt dan bij een gewone site, hebben wij uitgewerkt in het artikel over verdwenen bestellingen na een back-up.
Het resultaat
De waarschuwing in de browser verdween binnen drie dagen na de herbeoordeling. Het aantal bestellingen kroop in twee weken terug naar het oude niveau. De betaaldienstverlener heeft geen misbruik van de gestolen kaartgegevens kunnen vaststellen; de nepafrekenpagina lijkt vooral te zijn gebruikt om gegevens te verzamelen, niet direct om te betalen. Er is een melding gedaan bij de Autoriteit Persoonsgegevens, omdat niet uit te sluiten viel dat klantgegevens waren ingezien.
De directe kosten van het herstel waren beperkt. De gemiste omzet over negentien dagen was een veelvoud daarvan. Dat is bijna altijd de verhouding.
De lessen
Kijk niet alleen naar uw eigen scherm. Deze besmetting was onzichtbaar voor de eigenaar en zichtbaar voor precies de bezoekers die het meest opleverden. Controleer uw site af en toe op een telefoon, via een zoekopdracht, uitgelogd.
Een daling zonder verklaring is een signaal. Gelijkblijvend bezoek met dalende omzet is een technisch alarm, geen seizoenseffect. Als de cijfers scheef lopen, zoek dan door tot u weet waarom.
Beveiligingsupdates zijn geen gewone updates. Vier maanden uitstel was hier de hele oorzaak. Bij een webshop hoort een korter ritme, met een test op een staging-omgeving zodat bijwerken geen gok is.
Weet wie er belt als het misgaat. De ondernemer verloor de eerste avond uren met zoeken naar iemand die dit kon oppakken. Sindsdien loopt de shop mee in doorlopende beveiliging met dagelijkse back-ups en een vast aanspreekpunt. Dat is geen garantie tegen een hack, maar het verkort de tijd tussen “er is iets” en “het is opgelost” aanzienlijk.
Herkent u iets in dit verhaal, bijvoorbeeld omdat uw cijfers al weken niet kloppen: begin met kijken zoals een klant kijkt. Dat is de goedkoopste test die er is.


