Wenn WordPress-Malware zurückkommt, sobald man sie löscht: Wie wir SC v4.0.3 begegnet sind
Ein Erfahrungsbericht — und was wir daraus für andere Websitebetreiber mitgenommen haben
Wir sind eine Webdesign-Agentur mit Sitz in Osnabrück. Neben Design und Entwicklung kümmern wir uns auch um die Sicherheit und Wartung bestehender WordPress-Installationen. Bei Fragen zu Ihrem eigenen Projekt erreichen Sie uns hier.
Wenn WordPress-Malware zurückkommt, sobald man sie löscht: Wie wir SC v4.0.3 begegnet sind
Ein Erfahrungsbericht — und was wir daraus für andere Websitebetreiber mitgenommen haben
Vor Kurzem kam jemand auf uns zu, dessen WordPress-Seite sich merkwürdig verhielt: In der Google Search Console tauchten plötzlich fremdsprachige Casino-Seiten auf, im Backend fanden sich unbekannte Administrator-Accounts, und im Plugin-Bereich hatten sich Erweiterungen mit vertrauenswürdig klingenden Namen wie cloudflare-v2-23 oder wp-security-helper eingenistet. Was folgte, hat uns länger beschäftigt, als wir erwartet hätten.
Der eigentliche Ärger begann beim ersten Bereinigungsversuch: Wir löschten die verdächtigen Dateien — und sie waren innerhalb einer Minute wieder da. Willkommen bei SC v4.0.3, einer der hartnäckigsten Malware-Familien, die uns bisher untergekommen ist.
Wir schreiben diesen Beitrag, weil wir mittlerweile wissen, wie man diese Art von Befall wirklich loswird. Falls Sie ähnliche Symptome sehen, hilft Ihnen dieser Artikel hoffentlich weiter — oder Sie erkennen, wann es sinnvoll ist, jemanden dazuzuholen.
Woran Sie einen SC-Befall erkennen
Die Symptome sind meist eindeutig, wenn man weiß, worauf man achten muss:
In der Google Search Console erscheinen plötzlich Seiten, die es auf Ihrer Website nie gab — oft Casino, Pharma oder Kredit-Themen in fremden Sprachen. Die Seiten stammen intern von einem Autor mit ID 0, was in einer sauberen WordPress-Installation nicht vorkommt.
Im WordPress-Backend finden sich Administrator-Accounts, die Sie nie angelegt haben. Typische Namensmuster sind admin_[zufällige Hex-Zeichen], adm_..., administrator_... oder backup_....
Bei den Plugins tauchen Namen auf, die nach seriösen Erweiterungen klingen — es aber nicht sind. Die Autorenzeile ist der Verräter: „WpDevNinjas Team“ mit einer Website wp-ninjas.dev, die es in Wirklichkeit nicht gibt. Häufige Fake-Plugin-Namen sind cloudflare-v2-23, easypost, form-security, wp-security-helper, wp-cache-helper, blossomthemes-razorpay-contents oder cookie-viewer-woocommerce-fixer.
Im Dateisystem finden sich Dateien mit acht Hex-Zeichen im Namen (z.B. 294d7dc0.php) — oft in Paaren mit einer versteckten Variante .294d7dc0.php. Ebenso verräterisch: eine db.php oder advanced-cache.php direkt in wp-content/, die Sie nie installiert haben.
Warum die Malware immer zurückkommt
Das Frustrierendste an SC v4.0.3 ist genau das: Man löscht, sie kommt wieder. Der Grund liegt darin, dass die Malware nicht an einer Stelle sitzt, sondern an mehreren gleichzeitig. Jede dieser Stellen kann alle anderen wiederherstellen.
Wir haben insgesamt sieben verschiedene Persistenzmechanismen identifiziert:
Die Theme-Injektion klemmt einen obfuszierten PHP-Block in die functions.php des aktiven Themes. Man erkennt ihn an den Markern SC_TH_BEGIN:4.0.3: und SC_TH_END:4.0.3:. In den meisten Fällen ist die Datei nicht nur ergänzt, sondern der ursprüngliche Theme-Code komplett ersetzt — das führt zu einem der häufigsten Fehler bei der Bereinigung, dazu gleich mehr.
Ein mu-plugin namens glyph-importer-hq.php in wp-content/mu-plugins/. Diese Verzeichnis wird von WordPress automatisch geladen, ohne dass ein Plugin aktiviert sein muss. Wer nur die aktive Plugin-Liste bereinigt, übersieht sie zwangsläufig.
Ein reguläres Plugin ebenfalls namens glyph-importer-hq, das sich im Backend als „Pixel Widget Ink“ von einem angeblichen Entwickler „Jack Nelson“ ausgibt.
Drop-in-Dateien (db.php, advanced-cache.php) direkt in wp-content/. WordPress lädt diese automatisch bei jedem Aufruf.
Loader-Paare aus einer sichtbaren {8hex}.php und einer versteckten .{8hex}.php.
Ein Prepend-Eintrag in .user.ini via auto_prepend_file. Damit wird die Malware vor jedem einzelnen PHP-Aufruf ausgeführt — selbst wenn WordPress komplett neu installiert wird.
In der Datenbank wird ein Cron-Job (sc_cron_fetch) angelegt, der alle 89 Sekunden nachprüft, ob noch alles vorhanden ist — und was fehlt, wird wiederhergestellt. Dazu kommen eigene Tabellen (sc_*, wch_*, _awg_*) und die neuen Rogue-Admins.
Solange auch nur ein einziger dieser Mechanismen aktiv ist, kann er alle anderen zurückholen. Das ist die eigentliche Botschaft für jeden, der so einen Fall selbst angeht: Halbe Sachen führen zurück auf Null.
Die Fallen, in die wir getappt sind
Beim ersten Angehen sind uns mehrere Dinge passiert, die wir Ihnen gern ersparen würden.
Wir haben Zeitstempel geglaubt. Die Malware fälscht mtime und die user_registered-Werte in der Datenbank. Wir haben Dateien gefunden, die angeblich aus 2020 stammten, aber vor Minuten geschrieben worden waren. Nur die ctime einer Datei ist zuverlässig — die lässt sich vom Angreifer nicht manipulieren, weil sie vom Betriebssystem-Kernel bei jeder Inode-Änderung gesetzt wird.
Wir haben ältere Backups eingespielt. Das Backup war bereits kompromittiert, wir haben die Malware damit reinstalliert. Backups aus dem Webspace selbst sind bei einem Befall meist wertlos — sie können mitverseucht sein.
Wir haben den WordPress-Kern neu installiert und gehofft, das reicht. Der Reinstall überschreibt nur wp-admin/ und wp-includes/. Die Malware saß hauptsächlich in wp-content/ und in der Datenbank — dort ändert der Core-Reinstall nichts.
Wir haben den opcache übersehen. Auf vielen Shared-Hostings ist ein persistenter PHP-Bytecode-Cache aktiv (opcache.file_cache_only=1). Das bedeutet: Auch nachdem eine bösartige PHP-Datei gelöscht wurde, wird ihre kompilierte Version aus dem Cache weiter ausgeführt. Ohne das Cache-Verzeichnis (~/.opcache/) zu leeren, bleibt die Malware aktiv, obwohl die Quelldateien weg sind.
Wir haben sed benutzt, um die Payload aus functions.php zu schneiden. Bei den meisten befallenen Themes hat das die Datei komplett geleert, weil die Malware den Original-Code überschrieben hatte — der SC_TH_END-Marker stand in der letzten Zeile. Ergebnis: Fatal Errors und weiße Bildschirme. Die richtige Reihenfolge: erst prüfen, ob nach dem Endmarker noch echter Code folgt. Wenn nicht, muss das Theme frisch von wordpress.org geladen werden.
Was funktioniert hat
Der Erfolg kam erst mit einem koordinierten Vorgehen, bei dem alle Persistenzebenen gleichzeitig neutralisiert wurden. Grob in dieser Reihenfolge:
Zuerst der Cron-Job. Solange der Regenerationszyklus in der Datenbank läuft, ist jeder weitere Schritt zeitverschwendet. crontab -r auf Systemebene und der WordPress-Cron in der Datenbank auf leer setzen (option_name='cron').
Dann die Zugangswege schließen. Bei uns waren das drei:
- Das FTP/SSH-Passwort im Hosting-Kundenkonto ändern
- Alle Datenbank-Passwörter im Kundenkonto ändern und in den
wp-config.phpsynchronisieren - Alle WordPress-Admin-Hashes ungültig setzen und Sessions löschen
Die WordPress-Hashes lassen sich am einfachsten unbrauchbar machen, indem man den Wert auf etwas setzt, das kein bcrypt-Hash sein kann (z.B. CONCAT('LOCKED-', RAND())). Kein Passwort passt dazu, aber die „Passwort vergessen“-Funktion funktioniert weiterhin — Sie kommen also per Reset-Mail wieder rein.
Zusätzlich sollten die Salts in wp-config.php rotiert werden, damit bestehende Login-Cookies ungültig werden. Neue Salts bekommt man unter api.wordpress.org/secret-key/1.1/salt/.
Dann die Bereinigung — koordiniert. Alles in einem Rutsch:
- Alle infizierten Themes durch Originale ersetzen (vorher runterladen von wordpress.org)
- Fake-Plugins in der Datenbank aus
active_pluginsentfernen und die Ordner in Quarantäne verschieben - Drop-ins (
db.php,advanced-cache.php) entfernen - Alle
.user.inileeren - Alle Loader-Dateien mit 8-Hex-Namen verschieben
- Malware-ZIPs im Uploads-Ordner entfernen (auch die, die sich mit unauffälligen Namen tarnen)
- Rogue-Admins aus der Datenbank löschen
- Casino-Spam-Posts löschen (die mit
post_author=0sind ein guter Filter) - Malware-Tabellen droppen (
sc_*,wch_*,_awg_*) - Den opcache in allen Verzeichnissen leeren
Der letzte Punkt ist der, den man leicht vergisst und der bei Shared-Hosting-Installationen am häufigsten für „warum kommt sie schon wieder“ verantwortlich ist.
Der laufende Schutz
Nach der Bereinigung haben wir einen Watchdog eingerichtet, der alle 30 Sekunden prüft, ob sich einer der bekannten Malware-Indikatoren wieder zeigt. Ein zweites Skript prüft manuell, ob unbekannte PHP-Dateien in wp-content/ oder in der Site-Wurzel auftauchen — genau dort hatten wir später noch eine Backdoor gefunden, die per direktem POST-Aufruf angesprochen wurde und keinen Login brauchte.
Solche Backdoor-Dateien sind ein Grund, warum reine „ist der Login sicher?“-Prüfungen nicht ausreichen. Wenn eine PHP-Datei in wp-content/ liegt, ist sie über die URL aufrufbar — ganz ohne Benutzeranmeldung.
Was wir aus dem Vorfall gelernt haben
Für die eigene Zukunft und für alle, die ähnliches durchmachen, sind das unsere Konsequenzen:
Backups gehören außerhalb des Webspace. Wenn UpdraftPlus die Backups in denselben Ordner schreibt, aus dem es sichert, können sie im Ernstfall mitverseucht sein. Externes Ziel — Google Drive, S3, ein eigener Server — ist deutlich sicherer.
Ungenutzte Plugins sollten gelöscht werden, nicht nur deaktiviert. Ein alter Slider aus dem Jahr 2019, den niemand mehr benutzt, aber dessen Datei-Upload-Lücke seit sechs Jahren bekannt ist, bleibt eine offene Tür.
Neue Administrator-Accounts sollten alarmieren. Eine tägliche automatische Prüfung, die bei neuen Admins eine E-Mail schickt, hätte uns den Vorfall Wochen früher gezeigt.
In wp-content/ gehört nichts außer den vorgesehenen Dateien. Wir prüfen inzwischen regelmäßig gegen eine Whitelist. Alles, was dort auftaucht und nicht dazugehört, ist verdächtig.
Zeitstempel sind bei Malware-Vorfällen nicht vertrauenswürdig. Das gilt für Dateisystem-Werte genauso wie für Datenbank-Felder wie user_registered.
Wenn Sie ähnliches sehen
Wir wissen: Selbstbereinigung ist möglich. Sie kostet aber Zeit, Nerven und einiges an Erfahrung. Und wenn ein einziger Schritt in der falschen Reihenfolge kommt oder ein Versteck übersehen wird, geht die Odyssee wieder von vorn los.
Wenn Sie Symptome wie oben beschrieben auf Ihrer WordPress-Seite sehen und unsicher sind, ob Sie den Angriff wirklich vollständig loswerden — melden Sie sich gern bei uns. Wir haben inzwischen die Skripte und die Erfahrung, um einen SC-Befall zuverlässig und in überschaubarer Zeit zu bereinigen, ohne dass die Seite am Ende doch wieder infiziert ist.
Und falls Sie unsicher sind, ob Sie überhaupt betroffen sind: Ein Blick in Ihre Search Console und ein kurzer Check der Benutzerliste in WordPress kostet zehn Minuten. Das lohnt sich.
Wir sind eine Webdesign-Agentur mit Sitz in Osnabrück. Neben Design und Entwicklung kümmern wir uns auch um die Sicherheit und Wartung bestehender WordPress-Installationen. Bei Fragen zu Ihrem eigenen Projekt erreichen Sie uns unter Kontakt
