secaudit.eu
Notfall

WordPress wird immer wieder gehackt? So finden Sie die Hintertür

WordPress immer wieder gehackt? Diese Hintertüren überleben die Bereinigung: auto_prepend_file, mu-plugins, Fake-Plugins, Cron, Nachbarseiten, offene Lücken.

Von , AngelForce OÜ 8 Min. Lesezeit

Auch auf: English Français Español Italiano Polski Português Türkçe

Wenn WordPress nach einer Bereinigung immer wieder gehackt wird, hat der Angreifer mit ziemlicher Sicherheit noch einen Zugang. Entweder hat eine Hintertür die Bereinigung überstanden, oder die Lücke, über die er beim ersten Mal hereinkam, ist weiterhin offen. Ein frisch eingespielter WordPress-Core und ein paar gelöschte Dateien beheben keines der beiden Probleme.

Diese Anleitung setzt voraus, dass bereits bereinigt wurde. Sie geht die Stellen durch, die eine Bereinigung typischerweise überleben, und zwar in der Reihenfolge, in der der Code ausgeführt wird. Zu jeder Stelle gibt es eine konkrete Prüfung. Am Ende steht der Schritt, der den Kreislauf tatsächlich durchbricht.

Warum WordPress nach der Bereinigung immer wieder gehackt wird

Es gibt zwei Ursachen, und oft liegen beide gleichzeitig vor. Die erste ist Persistenz: Angreifer hinterlassen selten nur eine Hintertür. Sie platzieren mehrere an verschiedenen Stellen, damit die übrigen weiterlaufen, wenn Sie eine davon finden. Die zweite ist ein Einfallstor, das noch offen ist. Das kann ein verwundbares Plugin sein, ein gestohlenes Passwort oder eine Nachbarseite im selben Hosting-Konto.

Der Zeitpunkt liefert einen Hinweis. Eine erneute Infektion wenige Stunden nach der Bereinigung deutet meist auf eine überlebende Hintertür oder einen geplanten Job hin, der Dateien neu schreibt. Kommt die Infektion erst nach Tagen oder Wochen zurück, spricht das eher für eine offene Lücke, die jemand – oder ein Bot – erneut gefunden hat.

Offene Lücken werden schnell gefunden. Der Bericht State of WordPress Security in 2026 stammt von Patchstack, einem Anbieter, und sollte entsprechend gelesen werden. Demnach lag bei stark ausgenutzten Schwachstellen die gewichtete mediane Zeit bis zur massenhaften Ausnutzung bei 5 Stunden. Rund die Hälfte der Schwachstellen mit hoher Auswirkung wurde innerhalb von 24 Stunden ausgenutzt. Laut demselben Bericht gab es für 46 % der Schwachstellen zum Zeitpunkt der öffentlichen Bekanntgabe noch keinen Fix. Ein ungepatchtes Plugin ist also kein kleines Risiko, um das man sich nächste Woche kümmern kann.

Diagramm: der Kreislauf der Reinfektion und vier Ebenen, auf denen sich Hintertüren verstecken
Jede Bereinigung, die eine Ebene übersieht, hält den Kreislauf in Gang. Erst wenn das Einfallstor geschlossen ist und alle Zugangsdaten erneuert sind, ist er durchbrochen.

Vor der Suche: zuerst die Beweise sichern

Erstellen Sie eine vollständige Kopie der Dateien und der Datenbank und sichern Sie die Zugriffsprotokolle des Webservers, bevor Sie irgendetwas Weiteres löschen. Halten Sie anschließend die Zeitstempel der Dateien fest, damit Sie Änderungen später den Protokolleinträgen zuordnen können:

cd /path/to/site
find . -type f -printf '%T@ %TY-%Tm-%Td %TH:%TM %p\n' | sort -n > ~/file-times-$(date +%F).txt
wp db export ~/evidence-db-$(date +%F).sql

Der Datenbank-Export enthält personenbezogene Daten. Verschieben Sie diese Kopien deshalb vom Server auf einen sicheren Speicherort. Sonst tauchen sie bei der Suche nach Backups weiter unten auf und könnten versehentlich gelesen oder gelöscht werden. Führen Sie eine einfache Liste aller Dateien, Benutzer und Cron-Jobs, die Sie entfernen, jeweils mit Datum. Sie brauchen sie, um das Einfallstor zu finden. Und falls personenbezogene Daten betroffen waren, brauchen Sie sie auch, weil Sie nach Art. 33 Abs. 5 DSGVO jede Verletzung des Schutzes personenbezogener Daten dokumentieren müssen – auch solche, die Sie nicht melden. Die vollständigen Schritte zur Eindämmung finden Sie in unserem Plan zur Malware-Entfernung bei WordPress.

Hintertüren, die laufen, bevor WordPress lädt

Die PHP-Einstellung auto_prepend_file führt vor jeder PHP-Anfrage eine Datei aus – noch bevor WordPress lädt und bevor ein Sicherheits-Plugin überhaupt etwas mitbekommt. Genau deshalb ist sie bei Angreifern beliebt. Gesetzt werden kann sie in der php.ini, in einer .user.ini in jedem beliebigen Verzeichnis oder per php_value in der .htaccess (Apache mit mod_php). Durchsuchen Sie das gesamte Konto:

grep -Rn --include='*.ini' --include='.htaccess' -E 'auto_(prepend|append)_file' ~ 2>/dev/null
php --ini

php --ini zeigt, welche Konfigurationsdateien das PHP auf der Kommandozeile lädt. Das PHP des Webservers kann andere verwenden, prüfen Sie also zusätzlich die PHP-Einstellungen in Ihrem Hosting-Panel. Jeder Wert, der auf eine Datei zeigt, die Sie nicht kennen, ist ein Fund. Notieren Sie den Pfad, sichern Sie eine Kopie dieser Datei und entfernen Sie dann die Einstellung. Änderungen an der .user.ini greifen unter Umständen erst nach einigen Minuten, weil PHP diese Dateien zwischenspeichert.

Als Nächstes ist die wp-config.php dran. Eine saubere Datei enthält gegen Ende genau ein require_once ABSPATH . 'wp-settings.php'; und oberhalb des einleitenden Kommentarblocks keinerlei ausführbaren Code. Suchen Sie nach allem anderen:

head -n 5 wp-config.php
grep -nE 'eval\(|base64_decode|gzinflate|str_rot13|include|require' wp-config.php
awk 'length > 300 {print FILENAME": line "NR" is "length" chars"}' wp-config.php

Vergleichen Sie die Datei dann mit diff mit einer nachweislich sauberen Version aus einem älteren Backup. Haben Sie keine saubere Kopie, vergleichen Sie den Aufbau mit der wp-config-sample.php. Zusätzliche Includes, sehr lange Zeilen und Code vor dem Kommentarblock haben dort nichts zu suchen.

Verstecke in wp-content: mu-plugins und gefälschte Plugins

Must-Use-Plugins und Drop-ins

Alles in wp-content/mu-plugins wird bei jeder Anfrage automatisch ausgeführt. WordPress zeigt diese Plugins nur auf einem eigenen Reiter „Unverzichtbar“ der Plugin-Seite an, PHP-Dateien in Unterordnern erscheinen dort überhaupt nicht, und keines davon lässt sich im Dashboard deaktivieren. Viele Websites haben gar keine Must-Use-Plugins. Manche Hoster installieren eines für Caching oder Verwaltung.

ls -la wp-content/mu-plugins
wp plugin list --status=must-use
wp plugin list --status=dropin

Auch Drop-ins gehören auf die Liste: object-cache.php, advanced-cache.php und db.php direkt in wp-content. Sie sind legitim, wenn Ihr Cache-Plugin oder Ihr Hoster sie dort abgelegt hat. Erklärt nichts, was Sie installiert haben, ihre Anwesenheit, behandeln Sie sie als verdächtig.

Gefälschte und nachgeahmte Plugin-Ordner

Ein Plugin-Ordner ohne gültigen Plugin-Header taucht in WordPress nicht auf, seine PHP-Dateien lassen sich aber trotzdem direkt per URL aufrufen. Vergleichen Sie, was auf der Festplatte liegt, mit dem, was WordPress kennt:

ls -1 wp-content/plugins | sort > on-disk.txt
wp plugin list --field=name | sort > registered.txt
comm -23 on-disk.txt registered.txt

index.php und Ein-Datei-Plugins wie hello.php erscheinen in der Ausgabe. Alles andere sollten Sie sich genauer ansehen. Achten Sie auf Namen, die echte Plugins imitieren, etwa durch einen zusätzlichen Bindestrich, eine Versionsnummer im Ordnernamen oder Bezeichnungen wie „wp-security-core“. Führen Sie danach wp plugin verify-checksums --all aus. Das deckt allerdings nur Plugins ab, die auf WordPress.org gehostet sind. Bei Premium-Plugins laden Sie eine frische Kopie beim Hersteller herunter und vergleichen sie mit diff -r. Für den WordPress-Core folgen Sie unserer Anleitung zum Prüfen der WordPress-Checksummen.

Kürzlich geänderte PHP-Dateien

find wp-content -type f -name '*.php' -mtime -30 -printf '%TY-%Tm-%Td %p\n' | sort
find wp-content -type f -name '*.php' -ctime -30

Falls Sie den Core noch nicht neu installiert haben, ist -newer wp-includes/version.php ein weiterer brauchbarer Bezugspunkt. Angreifer können Änderungszeiten mit touch fälschen, die Statusänderungszeit (-ctime) dagegen nicht ohne Weiteres – führen Sie deshalb beide Befehle aus. PHP-Dateien im Upload-Verzeichnis behandeln wir gesondert in unserem Leitfaden zu Web-Shells in wp-content/uploads.

Persistenz in Datenbank und Zeitplanung: Cron, Admins, Anwendungspasswörter

WP-Cron-Ereignisse liegen in der Datenbank und überstehen damit jede Dateibereinigung. Lassen Sie sie sich anzeigen:

wp cron event list --fields=hook,next_run_relative,recurrence

Jeder Hook sollte zum Core oder zu einem Plugin gehören, das Sie kennen. Bei einem unbekannten Hook durchsuchen Sie den Code mit grep -Rn "hook_name" wp-content. Liegt der Code, der ihn registriert, in einem mu-plugin oder in einer Datei, die Sie nicht erklären können, haben Sie eine Hintertür gefunden. Ein Hook ohne zugehörigen Code kann bedeuten, dass die Hintertür entfernt wurde, das Ereignis aber übrig geblieben ist. Löschen Sie es mit wp cron event delete hook_name.

Prüfen Sie anschließend die Serverseite: crontab -l für den Hosting-Benutzer sowie den Cron-Bereich in Ihrem Hosting-Panel. Ein Job, der curl oder wget aufruft oder in das Web-Root-Verzeichnis schreibt, kann jede Nacht still und leise eine Hintertür wiederherstellen.

Dann folgen die Konten. Dieser Befehl listet alle Administratoren auf und danach die Anwendungspasswörter jedes einzelnen:

wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
for id in $(wp user list --role=administrator --field=ID); do echo "User $id"; wp user application-password list "$id"; done

Anwendungspasswörter funktionieren auch nach einer Passwortänderung weiter. Ein unbekannter Eintrag hier ist deshalb genauso ernst zu nehmen wie ein unbekannter Admin. Die vollständige Überprüfung beschreibt unser Leitfaden zu WordPress-Benutzerrollen.

Suchen Sie zum Schluss nach eingeschleusten Skripten in Inhalten und Einstellungen. Ersetzen Sie wp_, falls Ihr Tabellenpräfix anders lautet:

wp db search 'script src=' wp_options wp_posts --stats
wp db search 'atob(' wp_options wp_posts --stats
wp db query "SELECT option_name, LENGTH(option_value) AS size FROM wp_options WHERE autoload IN ('yes','on','auto','auto-on') ORDER BY size DESC LIMIT 20;"

Die ersten beiden Suchen finden eingebundene externe Skripte und die Base64-Dekodierung, die eingeschleustes JavaScript häufig nutzt. Die Abfrage listet die größten automatisch geladenen Optionen auf. Ein unbekannter Optionsname mit großem Wert verdient einen zweiten Blick.

Das Audit-Plugin von secaudit.eu zeigt diese Anzeichen einer Kompromittierung an einer Stelle: versteckte Admins, verdächtige Cron-Einträge, Spam in der Datenbank und Abweichungen bei den Core-Checksummen. Es erkennt und meldet – die Entscheidung, was entfernt wird, bleibt bei Ihnen → secaudit.eu

Der Rest des Hosting-Kontos: Nachbarseiten und alte Kopien

Beim Shared Hosting laufen oft mehrere Websites unter einem einzigen Systembenutzer. Eine infizierte Staging-Kopie, eine vergessene Installation unter /old/ oder /test/ oder ein Backup-ZIP im Web-Root infiziert die gerade bereinigte Website erneut. Verschaffen Sie sich einen Überblick über alles im Konto:

find ~ -name wp-config.php 2>/dev/null
find ~ -type d -name wp-includes 2>/dev/null
find ~ -type f \( -name '*.zip' -o -name '*.tar.gz' -o -name '*.sql' \) 2>/dev/null

Bereinigen Sie alle Websites im Konto gleichzeitig oder löschen Sie diejenigen, die niemand mehr braucht. Teilen sich alle Websites einen SFTP-Benutzer und einen Datenbankbenutzer, kann jede kompromittierte Website in alle anderen schreiben. Trennen Sie sie, wo immer möglich, in eigene Benutzer oder eigene Hosting-Konten.

Einfallstor schließen und alle Zugangsdaten auf einmal erneuern

Das Einfallstor finden Sie in den Zugriffsprotokollen rund um den Zeitstempel der ersten Infektion. Suchen Sie nach POST-Anfragen an ungewöhnliche Dateien und an die Endpunkte des Plugins, das Sie im Verdacht haben:

grep '"POST ' access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -30

Aktualisieren Sie das verwundbare Plugin. Gibt es keinen Fix oder wird das Plugin nicht mehr gepflegt, ersetzen Sie es. Brauchen Sie es nicht, löschen Sie es. Deaktivieren reicht nicht, denn die Dateien bleiben auf dem Server und sind weiterhin per URL erreichbar.

Erneuern Sie danach sämtliche Zugangsdaten und Schlüssel in einem Durchgang – nach der Bereinigung, nicht vorher. Wer zu früh wechselt, liefert einer überlebenden Hintertür einfach die neuen Werte.

  • Alle WordPress-Administratorpasswörter und sämtliche Anwendungspasswörter
  • Datenbankpasswort: im Hosting-Panel ändern, dann DB_PASSWORD in der wp-config.php anpassen
  • Login für das Hosting-Panel, SFTP-Passwörter und SSH-Schlüssel (unbekannte Schlüssel entfernen)
  • In Plugins hinterlegte API-Schlüssel (Zahlung, SMTP, CDN, Backup-Speicher)
  • Sicherheitsschlüssel und Salts: wp config shuffle-salts

Wiederholen Sie dieselben Prüfungen nach 24 Stunden und noch einmal nach 7 Tagen und vergleichen Sie die Ergebnisse mit Ihren Beweisdateien. Taucht ein mu-plugin, ein Cron-Ereignis oder eine geänderte Datei wieder auf, gibt es noch etwas, das Sie nicht gefunden haben.

FAQ

Ab wann sollte ich das nicht mehr selbst machen?

Spätestens bei der zweiten Reinfektion – oder sofort, wenn Kundendaten offengelegt worden sein könnten oder es sich um einen Shop mit Bestellungen handelt. Dann gehört professionelle Incident Response ins Haus. Sind personenbezogene Daten betroffen, prüfen Sie außerdem, ob die 72-Stunden-Meldung nach DSGVO an die Aufsichtsbehörde greift. Unser Leitfaden zur 72-Stunden-Meldung einer Datenpanne erklärt, wann die Frist zu laufen beginnt.

Reicht es, ein Backup einzuspielen?

Nur wenn das Backup älter ist als die erste Hintertür und Sie das Einfallstor geschlossen haben. Andernfalls spielen Sie das Problem gleich mit der Website zurück.

Hören die Angriffe auf, wenn ich alle Passwörter ändere?

Nein. Eine überlebende Hintertür braucht kein Passwort. Erneuern Sie Zugangsdaten nach der Suche, nicht stattdessen.

Dieser Artikel ist eine allgemeine Information und keine Rechtsberatung.

Prüfen Sie Ihre eigene Website

Security Audit & Compliance ist das WordPress-Plugin von secaudit.eu: Es sucht nach Malware, verstecktem Spam, veränderten Kerndateien und unsicherem Code und ordnet seine Befunde DSGVO Art. 32, NIS2 Art. 21 und den OWASP Top 10 zu.

Sehen, was das Plugin prüft
Melike Görel

Melike Görel schreibt die secaudit.eu-Ratgeber zu WordPress-Sicherheit und EU-Compliance für die AngelForce OÜ, das Softwareunternehmen aus Tallinn hinter secaudit.eu.

Mit KI-Unterstützung erstellt und vor der Veröffentlichung auf Fakten geprüft. Dieser Artikel ist eine allgemeine Information und keine Rechtsberatung.