knallt.com

  • Ein kompromittierter Webspace: Was ich falsch eingeschätzt habe und wie ich ihn bereinigt habe

    Der erste Hinweis sah nach einem einzelnen WordPress-Problem aus: Plötzlich tauchten tausende URLs auf, die niemand angelegt hatte. Einige gaben Shop-Inhalte aus, die mit der eigenen Website nichts zu tun hatten. Das war ärgerlich, aber zunächst kein Grund, den gesamten Webspace zu verdächtigen. Überraschend wurde es erst, als ich nicht bei dieser einen Seite stehenblieb.

    Auf demselben Shared Hosting lagen mehrere WordPress-Installationen, ein paar kleinere Eigenentwicklungen und alte Testprojekte. Der erste Impuls war verständlich: die betroffene Seite aufräumen, das Passwort ändern, weiterarbeiten. Das wäre zu wenig gewesen. Der Befund zeigte, dass der Webspace als Ganzes behandelt werden musste.

    Was tatsächlich gefunden wurde

    In mehreren WordPress-Instanzen waren Core- und Konfigurationsdateien verändert worden. Es gab Spam-Pfade, die von WordPress nicht als reguläre Inhalte angelegt worden waren, und Dateien an Stellen, an denen sie nicht hingehören.

    Noch lehrreicher waren die Eigenentwicklungen. Sie waren keine WordPress-Seiten. Trotzdem enthielten mehrere davon plötzlich Verzeichnisse wie wp-admin und wp-includes, dazu Dateien mit Namen wie wp-active.php, old-cache.php oder class-wp-updates.php. Das war kein merkwürdiges Framework-Feature und auch kein vergessener Test. Es waren identische, fremde Dateibäume, die sich über mehrere Webroots verteilt hatten.

    Dateinamen allein sind kein Beweis. In diesem Fall kamen weitere Signale hinzu: derselbe Inhalt und dieselben Dateihashes an mehreren Orten, typische Verschleierung und Funktionen für Uploads oder Kommandoausführung. Das reicht, um nicht mehr über einzelne Dateien zu diskutieren. Man muss den Befund sichern und handeln.

    Bildplatzhalter: Anonymisierte Dateibaum-Ansicht mit einem unerwarteten wp-admin-Ordner in einer Eigenentwicklung. Domain, Benutzername, vollständiger Serverpfad und Zeitstempel schwärzen.

    Erst sichern, dann verändern

    Der wichtigste Schritt war auch der unattraktivste: nichts vorschnell löschen. Vor der Bereinigung habe ich die betroffenen Webroots und Datenbanken gesichert, Hashes festgehalten und Schad-Dateien in eine Quarantäne außerhalb der öffentlich erreichbaren Verzeichnisse verschoben.

    Das ist keine Förmlichkeit. Ohne eine unveränderte Kopie lässt sich später weder nachvollziehen, was passiert ist, noch eine falsche Entscheidung zurückdrehen. Auch für einen Hoster oder eine Versicherung sind nachträglich erzählte Dateinamen deutlich weniger wert als ein gesicherter Bestand mit Prüfsummen.

    Danach habe ich getrennt gearbeitet. WordPress bekam frischen Core aus der offiziellen Quelle. Plugins wurden nur aus vertrauenswürdigen Quellen neu installiert. Ein kommerzielles Theme wurde aus dem aktuellen Herstellerpaket eingespielt. Alte Theme- oder Plugin-Verzeichnisse aus dem betroffenen Webspace waren dabei ausdrücklich keine Quelle für eine Wiederherstellung.

    Das wirkt pedantisch. In der Praxis macht es einen Unterschied. Ein altes Backup kann gleichzeitig das Design retten und die Hintertür zurückbringen. Visuelle Wiederherstellung und technische Bereinigung sind zwei verschiedene Aufgaben.

    Wo ich zu eng gedacht habe

    Ich habe zunächst zu eng gedacht. Weil eine sichtbare WordPress-Seite betroffen war, lag mein Fokus auf WordPress. Die Eigenentwicklungen schienen davon getrennt zu sein. Tatsächlich hatten sie nur keinen WordPress-Stack, aber trotzdem fremde Dateien im Webroot.

    Der zweite Fehler wäre beinahe das blinde Zurückspielen gewesen. Bei einer Seite fehlte nach der Bereinigung zunächst der Header. Die alte Installation enthielt passende Erweiterungen. Sie einfach zurückzukopieren hätte das sichtbare Problem schnell gelöst, aber auch nicht geprüften Code wieder produktiv gemacht. Die saubere Lösung war, die fehlende Erweiterung frisch vom Hersteller zu beziehen und erst dann wieder zu aktivieren.

    Drittens: Ein grüner Scan ist keine Entwarnung für alles. Ein Scan erkennt bekannte Muster, verdächtige Dateinamen und bestimmte Code-Konstruktionen. Er sagt nicht zuverlässig, ob jede einzelne Anwendung frei von unbekannten Fehlern ist. Deshalb gehören frische Quellen, Tests und wiederholte Prüfungen dazu.

    Die richtige Bereinigung hängt vom System ab

    Bei WordPress ist die Reihenfolge klar: erst Sicherung und Forensik, dann Core, Themes und Plugins aus sauberen Quellen wiederherstellen. Danach müssen Administratoren, Datenbankzugänge, FTP- oder SFTP-Zugänge, Deploy-Secrets und Anwendungspasswörter neu bewertet und rotiert werden. Auch Cronjobs, mu-plugins, Rewrite-Regeln und unbekannte Benutzerkonten gehören in die Prüfung.

    Bei Eigenentwicklungen ist ein frischer Deployment-Stand aus Git oft besser als eine Reparatur im Live-Dateisystem. Dort weiß man, welche Dateien zur Anwendung gehören. Ein einfaches Overlay-Deployment reicht aber nicht: fremde Dateien bleiben dann oft liegen. Besser ist es, den Webroot erst vollständig zu sichern und zu leeren oder zu quarantänisieren und anschließend nur den geprüften Repository-Stand auszurollen.

    Bei reinen Testprojekten war die Entscheidung noch einfacher. Sie brauchten nicht sofort wieder online zu sein. Die gesamten Webroots wurden archiviert und vom öffentlichen Hosting entfernt. Wenn eines davon wieder gebraucht wird, kommt es als frischer Checkout in eine zugriffsgeschützte Testumgebung zurück, nicht aus der alten Kopie auf dem Server.

    Bildplatzhalter: Bereinigungsablauf als einfache Grafik: sichern, prüfen, aus vertrauenswürdiger Quelle wiederherstellen, Zugänge rotieren, erneut testen. Keine internen Pfade, Kontonamen oder Hashwerte zeigen.

    Was danach geprüft werden muss

    Nach einer Bereinigung reicht es nicht, dass die Startseite lädt. Für jede Website sollten mindestens diese Fragen beantwortet werden:

    • Liefert die normale Startseite den erwarteten Status und Inhalt?
    • Sind bekannte Spam-Pfade dauerhaft mit 404 oder 410 beendet?
    • Sind unnötige Schnittstellen eingeschränkt, etwa XML-RPC, wenn sie nicht gebraucht werden?
    • Gibt es neue oder unerwartete Administratoren, Cronjobs, Rewrite-Regeln oder Dateien?
    • Stimmen aktive Plugins, Themes und Versionen mit dem erwarteten Stand überein?
    • Sind Backups vorhanden, aber außerhalb des öffentlich erreichbaren Webroots?
    • Wurden alle Zugangsdaten geprüft und die betroffenen Zugänge erneuert?

    Bildplatzhalter: Anonymisierte Prüfliste oder Terminal-Ausgabe mit nur Statuscodes. URLs, Hostnamen, Pfade und Kennungen schwärzen.

    Die unangenehme Lehre

    Shared Hosting verleitet dazu, Websites als einzelne Inseln zu behandeln. Aus Betriebssicht teilen sie aber oft Dateien, Zugänge, Deploy-Wege und Fehler. Wenn mehrere Projekte auf einem Account liegen, muss bei einem bestätigten Befall immer der gesamte Account in die Untersuchung.

    Das bedeutet nicht, jedes Verzeichnis zu löschen. Es bedeutet, Beweise zu sichern, Grenzen sauber zu ziehen und nur aus Quellen wiederherzustellen, denen man vertraut. Git-Repositories, Herstellerpakete und frische offizielle Downloads sind solche Quellen. Eine Kopie vom kompromittierten Server ist es nicht.

    Die eigentliche Arbeit endet auch nicht mit dem letzten gelöschten Backdoor-Skript. Sie endet erst, wenn die Anwendungen wieder funktionieren, die alten Zugänge keinen Schaden mehr anrichten können und spätere Prüfungen denselben sauberen Zustand bestätigen.