WordPress·5 min lezen

Spam blijft staan na het opschonen: de mappen die WordPress overslaan

Je site is opgeschoond, de database is schoon, de cache is geleegd en toch staat de spam er nog. Dan serveert je webserver geen WordPress meer, maar echte mappen met een index.html. Zo vind je ze en zo ruim je ze op.

Op mijn site staan nog spampagina's op adressen die ik niet ken, terwijl
WordPress schoon is en de cache geleegd. Kijk of er op die adressen echte
mappen met een index.html in de webroot staan en zet op een rij welke dat
zijn. Nog niets verwijderen.

Dit is het scenario: je site is gehackt en opgeschoond. De verdachte bestanden zijn weg, de onbekende beheerder is verwijderd, alle wachtwoorden zijn vervangen, de database is nagekeken. Je hebt de cache geleegd, twee keer.

En toch: je opent een van die spamadressen en de spampagina staat er nog steeds. Precies hetzelfde, geen verschil.

Op dat moment denkt bijna iedereen hetzelfde: het zit nog in de cache. Dat is het bijna nooit.

Wat er echt gebeurt

WordPress werkt met één ingang. Elk adres komt binnen bij index.php, en WordPress zoekt uit welke pagina je bedoelt. Dat werkt via een regel in .htaccess met een belangrijke voorwaarde erin: stuur het verzoek alleen naar WordPress als er geen echt bestand en geen echte map op dat pad bestaat.

Daar zit het gat. Maakt een aanvaller voor elk spamadres een echte map aan met een index.html erin, dan bestaat die map. De voorwaarde slaat aan, de webserver serveert dat bestand, en WordPress komt niet eens aan de beurt.

Je kunt dus de hele WordPress-installatie schoonpoetsen, de pagina's in de editor nakijken en de cache tien keer legen. Het doet niets, want je kijkt naar een laag die daar helemaal onder zit. Het lijkt op hardnekkige cache en het gedraagt zich als hardnekkige cache, maar het is gewoon een bestand op schijf.

Waarom aanvallers dit doen: deze pagina's zijn voor zoekmachines. Ze staan vol links naar iets dat ze willen verkopen en ze misbruiken de goede naam van jouw domein. Daarom worden het er ook meteen veel, niet één.

Hoe je het in één verzoek ziet

Je hoeft hiervoor niet in bestanden te zoeken. Het verschil zit in de antwoordkoppen.

Vraag de koppen op van zo'n spamadres en vergelijk ze met een pagina waarvan je zeker weet dat WordPress hem maakt. Een statisch bestand levert twee kenmerken op die een WordPress-pagina niet heeft: een last-modified-kop, en een etag die is opgebouwd uit de bestandsgrootte en het wijzigingsmoment. Staat die last-modified precies in de periode van de hack, dan weet je het zeker.

Een pagina die WordPress zelf maakt, heeft die kenmerken niet, ook niet als hij uit de cache komt.

Vraag van deze drie adressen alleen de antwoordkoppen op en zet ze naast
elkaar in een tabel: statuscode, last-modified en etag. Zeg bij elk adres of
het een statisch bestand of een pagina van WordPress is.

De lijst die de aanvaller voor je heeft gemaakt

Nu moet je weten hoeveel het er zijn. En hier zit een wrange grap in: de aanvaller heeft die lijst zelf achtergelaten.

Deze aanpak werkt namelijk alleen als zoekmachines de pagina's vinden, dus wordt er een eigen sitemap neergezet in de webroot, vaak samen met een aangepaste robots.txt. Die sitemap is de volledige opsomming van alles wat er is aangemaakt. Soms staat er ook in elke map nog een eigen sitemap.

Dus: zoek in de webroot naar sitemapbestanden die je niet kent, en vergelijk die met de sitemap die je eigen SEO-plugin genereert. Wat erin staat en niet van jou is, is je werklijst.

Opruimen, en de valkuil daarbij

Twee dingen gaan hier vaak mis.

Alleen de index.html verwijderen is niet genoeg. Haal je het bestand weg en laat je de map staan, dan bestaat de map nog. De voorwaarde in .htaccess kijkt naar de map, niet naar het bestand. Het resultaat is dat bezoekers vanaf dan een foutmelding krijgen in plaats van de spam. Opgelost is het niet, en in de zoekresultaten verandert er niets. Verwijder de hele map.

De bestanden in de webroot vergeet je. De sitemapbestanden en de aangepaste robots.txt staan niet in een map, maar los. Die moeten er ook uit, anders blijven zoekmachines de oude adressen opvragen.

Verwijderen is onomkeerbaar, dus hier krijg je in de assistent altijd een goedkeuring voor. Vraag eerst de lijst op, bekijk hem, en geef dan pas toestemming voor het verwijderen. Verwijderen gaat bij ons via de prullenbak van je hostingaccount, dus je hebt nog een periode waarin je iets terug kunt halen als je te veel hebt meegenomen.

Controleren of je klaar bent

De controle is een rondje langs alle adressen. Twee lijsten naast elkaar: de adressen uit de sitemap van de aanvaller, en de adressen van je echte pagina's.

Van de eerste lijst wil je een foutcode zien, want die pagina's horen niet te bestaan. Van de tweede lijst wil je allemaal werkende pagina's zien, zodat je weet dat je niet per ongeluk iets van jezelf hebt weggegooid. Dat is één opdracht:

Vraag de statuscode op van alle adressen in deze lijst en van alle pagina's
van mijn WordPress-site. Zet in een tabel welke nog een pagina teruggeven en
welke een foutcode. Markeer alles dat niet klopt.

Daarna is er nog één ding: de zoekmachines weten het nog niet. De adressen zijn geïndexeerd, en dat gaat niet weg omdat de bestanden weg zijn. Dien je eigen sitemap opnieuw in en vraag in Search Console om verwijdering van de ergste adressen. Reken op weken, niet op dagen.

En loop daarna de gewone hack-controle nog een keer na, zodat je zeker weet dat de ingang zelf ook dicht is: wat de hack-controle nakijkt.

Veelgemaakte fouten

De cache nog een keer legen. Als dit het probleem is, verandert legen niets. Kijk eerst naar de antwoordkoppen, dan weet je in dertig seconden of je naar een bestand of naar een pagina kijkt.

Denken dat het terug is omdat de hack terug is. Deze pagina's zijn achtergebleven, niet opnieuw geplaatst. Dat is een belangrijk verschil, want het betekent dat je opruimwerk niet voor niets was.

Alleen de index.html weghalen. Dan ruil je spam om voor een foutmelding. Verwijder de hele map.

Je eigen mappen meenemen. Veel sites hebben echte mappen in de webroot die ergens voor dienen, bijvoorbeeld een oude landingspagina of een map met downloads. Ga op de lijst af en verwijder niet op gevoel.

Stoppen zodra je site weer klopt. De zoekresultaten lopen achter. Laat de controle nog een paar weken staan en kijk of er niets terugkomt. Komt het wel terug, dan is de ingang nog open en is dat een ander probleem dan dit.

MK
Maarten Keizer

Oprichter van Invoker. Ruim twintig jaar hosting, systeembeheer en webdevelopment; bouwt de Claude-hosting zelf en test alles eerst op de eigen servers.

over maarten