Schwupps, da war das WordPress weg – zur Lücke im WP GDPR Compliance Plugin

Oder vielmehr gehackt. Dank der Sicherheitslücke im WordPress GDPR Plugin. Der erste Gedanke: Was für eine Scheiße! Aber der Reihe nach.

Zwar halte ich meine WordPress-Installationen durchaus aktuell, die automatische Update-Funktion ist aktiviert, aber von Zeit zu Zeit erfordern die verwendeten Plugins und/oder Themes es dennoch, dass man sich um die jeweiligen Updates kümmert. Diesmal waren die bösen Buben (gehen wir mal davon aus, dass es keine Mädels waren) jedoch schneller. Was war passiert?

Eine Schwachstelle in WP GDPR Compliance

Am Abend des 08.11.2018 erhielt ich zwei Mails über neue Benutzer in dieser WordPress-Installation. Das ist durchaus ungewöhnlich, da ich ansonsten der einzige Nutzer hier bin. Sollte sich mal ein Leser auf diese Seiten verirren, ist das schließlich ohne Registrierung möglich. Dummerweise habe ich weder die erste Mail, die um 14:51 Uhr geschickt worden ist, noch die zweite Registrierungs-Mail von 18:32 Uhr erhalten. Denn Google bzw. Gmail hat sie als SPAM interpretiert, na danke. Zwar war der Inhalt nicht aufregend und auch die darin enthaltene Mailadresse legt durchaus einen gewissen Spamverdacht nahe, aber die Benachrichtigung an sich war ja von mir gewünscht und alles andere als Spam.

Anzeige

 

Um 23:41 Uhr und um 23:46 Uhr wurden wiederum zwei Mails zugestellt, diesmal glücklicherweise nicht im Spamverdacht, sondern in meinem Eingangspostfach. Ein Benutzer “t2trollherten” und “t3trollherten” hätten ihre Passwörter geändert. Wie bitte? Wer?

Ich loggte mich schnell ein – das war immerhin noch möglich und staunte nicht schlecht, als ich sah, dass es diese zwei Benutzer tatsächlich gab. Und noch viel schlimmer – sie hatten “administrator”-Rechte. Daraufhin ergab sich bei mir erstmal ein ziemlich großes “WTF?!?”, gefolgt von Googlen nach eben diesen Namen.

Und tatsächlich fand sich bereits einiges, eine Sicherheitslücke im Plugin “WP GDPR Compliance”, die zwar zu dem Zeitpunkt bereits behoben war, aber alle Versionen vor 1.4.3 waren gefährdet. Dank der allgemeinen DSGVO-Panik im Frühjahr dieses Jahres handelte sich um ein viel genutztes Plugin, insofern befand es sich auch auf meinen WordPress-Installationen. Diese habe ich daraufhin ebenfalls auf verdächtige Aktionen bzw. User untersucht und das Plugin aktualisiert. Tatsächlich war nur diese eine WordPress-Installation betroffen – immerhin etwas.

Es fanden sich auch bereits etliche Berichte, z.B. auf Twitter oder Diskussionen zum Thema bei Reddit.

Da ich den Fall erstmal genauer untersuchen wollte, habe ich zunächst ein Komplettbackup durchgeführt, in dem sich auch ein Dump der Datenbank und alle potenziell kompromittierten Dateien befinden sollten. Danach habe ich die WordPress-Installation komplett herunter gefahren. Dank des Einsatzes von Docker, wie im Artikel “Howto: WordPress im Docker Swarm Mode mit Nginx-Proxy auf einem Host” beschrieben ließen sich alle Server-Dienste, die für dieses Blog zuständig waren, unabhängig von anderen Diensten stoppen.

Anschließend habe ich mir die Datenbank-Dumps angesehen, und zwar zum einen die kompromittierte Version mit den neuen Benutzern, als auch eine Fassung aus einem vorherigen Backup, in denen sich noch keine Anzeichen der neuen Admin-User befanden. Um es klar zu sagen – der Vergleich der Datenbank-Dumps ist ein Gräuel! Und nicht etwa, weil der Dump so groß gewesen wäre, sondern einfach wegen der Datenbank-Struktur und der Speicherung als EAV, was hier nicht Erste Allgemeine Verunsicherung bedeutet, sondern eine Art von Entity-Attribute-Value-Struktur. Gekrönt nur noch durch die Nutzung von serialisierten Arrays, deren Inhalte als Werte in der Datenbank landen. Soll heißen – unübersichtlicher geht es nicht mehr. Zwar ließen sich die neuen User in der Tabelle “wp_users” schnell finden, aber ob sie weiteres Unwesen getrieben hatten, oder ob das Anlegen der Userkonten vielleicht nur der Vorbereitung eines größeren Angriffs diente, konnte ich ad hoc nicht feststellen.

Wiederherstellen des Systems

Somit gab es nur einen Ausweg – das Wiederherstellen aus dem Backup. Für Backups nutze ich seit geraumer Zeit das Plugin BackWPup, und zwar in der freien Version. Das Plugin ist meiner Ansicht nach spitze, es wird jeden Tag ein  Komplettbackup angelegt, inkl. eines Datenbank-Dumps.

Die Sicherungsdatei wird anschließend auf meinen (externen) Backup-Speicher kopiert, dazu nutze ich die Hetzner Storagebox mit einem Sub-User, d.h. für jede zu sichernde Website ist ein Sub-User angelegt, der wiederum ein eigenes Passwort besitzt und nur Zugriff auf seine eigenen Dateien hat. Zwar hätten WordPress-Administrator-Accounts auch darauf Zugriff gehabt, es wäre somit möglich gewesen, alle Backup-Dateien zu kompromittieren, andererseits zeigten die Upload-Daten keine Änderung auf den ersten Blick an, ebenfalls war der Datenbank-Dump noch ohne die neuen, unerwünschten Gäste vorhanden. Ebenfalls gehe ich davon aus, dass eher Skripte die Hacks gestartet haben, als dass tatsächlich im tiefsten Russland ein mit Hoody gekleideter, FSB-gesteuerter Hacker-Nerd mit mindestens drei Displays, auf denen grün auf schwarz Matrix-like Codes herauf scrollen, nun meine kleine Site übernehmen wollte… Dennoch bestand der erste Schritt darin, ein neues Passwort für den Backup-User auf dem Storage-System zu generieren.

Nun musste das System neu aufgesetzt werden. Die ZIP-Datei der Komplettsicherung hatte ich bereits auf das Host-System kopiert. Es wird empfohlen, auf ein Backup zurück zu greifen, was vor dem 06.11.2018 erstellt worden war. Inzwischen gibt es weitere Artikel, die sich mit dem Sicherheitsproblem beschäftigen und auf denen Tipps gegeben werden, was alles überprüft werden sollte. Jedoch halte ich diese Tipps mitunter für problematisch. Wie soll man sinnvollerweise eine komplette WordPress-Installation auf neue Dateien überprüfen? Angesichts des Umfangs je nach Anzahl der verwendeten Plugins würde einem kaum eine neue Datei auffallen, zumindest wenn sie sich nicht durch (ebenfalls modifizierbare) Merkmale wie ein File-Datum bemerkbar macht. Allein meine WordPress-Installation mit wenigen Plugins besitzt über 11000 Dateien. Eine schnelle Prüfung anhand des File-Datums brachte hingegen keine Ergebnisse, d.h. auf den ersten Blick war nichts neu erstellt worden.

Inzwischen hat es die Lücke auch zu Heise Online geschafft, dort wird vermeldet, dass Webshells unter dem Namen “wp-cache.php” hinterlassen worden waren. Eine derartige Datei konnte ich in dem gestern gesicherten Filesystem immerhin nicht finden, ebenfalls keine anderen Anzeichen von neu hochgeladenen Themes oder ähnliche Artefakte.

Insgesamt halte ich es für wesentlich sinnvoller, auf ein Backup zurück zu greifen und ggf. Beiträge, die darin noch nicht enthalten sind, anschließend zu ergänzen. Zur Not könnten diese aus einem neueren Datenbank-Dump entnommen werden, wobei nicht die komplette Datenbank genutzt wird, sondern nur die relevanten Inhalte aus der Zeit zwischen dem verwendeten Backup und der kompromittierten Fassung.

Da ich nicht täglich neue Artikel hinzufüge, konnte ich mir jedoch ein derartiges Vorgehen sparen. Einzig auf ein paar Statistik-Daten, gesammelt mit dem Plugin WP Statistics, musste ich verzichten, aber das erschien mir angesichts des Umfangs der Sicherheitslücke verschmerzbar.

Für die MySQL-Passwörter nutze ich Docker Secrets. Zwar ist die Datenbank nur innerhalb der Docker Services erreichbar, aber natürlich habe ich auch die alten Passwörter durch neue ersetzt, d.h. die alten Docker Secrets-Einstellungen gelöscht und neu angelegt:

Anzeige

Da BackWPup alle Dateien gesichert hatte (naja, zumindest fast, siehe unten), bestand der nächste Schritt darin, das bisherige WordPress-Verzeichnis zu löschen (oder an einen anderen Ort zwecks Sicherung zu verschieben) und das Backup darin zu entpacken.

WordPress befindet sich auf meiner Installation im Verzeichnis “html”, das wiederum in den Container gemountet wird. Somit:

Ebenfalls habe ich die MariaDB-Datenbank komplett entfernt, denn beim Anlegen via Docker-Image werden alle notwendigen Dateien erstellt, falls nicht vorhanden. Somit musste danach nur noch der Datenbank-Dump eingespielt werden.

Den Dump, der sich im Hauptverzeichnis des Backups befindet, habe ich dann ins Verzeichnis “mariadb/data” kopiert, damit er innerhalb des MariaDB-Containers gelesen werden konnte.

Da inzwischen auch neue Versionen der zugrunde liegenden Docker-Images php-fpm-swrm und nginx-swrm entstanden waren, sollten diese auch genutzt werden. Somit habe ich die Images per docker pull <image> herunter geladen und in einem nächsten Schritt dafür gesorgt, dass auch die noch laufenden Docker-Services ein Update der Images verwenden. Im Beispiel:

Danach musste erstmal das neue MariaDB-Passwort in der Datei “wp-config.php” eingerichtet werden – einfach das alte Passwort durch das neue ersetzen. Ebenfalls habe ich WordPress neue Sicherheitsschlüssel gegönnt, eine Erläuterung siehe z.B. in diesem Artikel. Diese Schlüssel können mittels WordPress-API sogar relativ einfach generiert werden.

Danach konnte der Docker-Stack wieder gestartet werden. Bevor WordPress wieder funktionierte, musste natürlich erstmal der Datenbank-Dump eingespielt werden. Nachdem also der Datenbank-Container lief, habe ich mich dort hinein begeben (docker exec -it <containername> bash) und die Daten wiederhergestellt:

Anschließend hätte WordPress wieder erreichbar sein sollen. Hätte… Ja, wenn nicht zwei Plugins angezeigt hätten, dass sie ein Problem hatten. Warum auch immer, aber beim Backup wurden aus dem Advanced-Ads-Plugin Dateien namens config.php aus diversen modules-Verzeichnissen nicht gesichert. Und genau diese waren zwingend notwendig, da ansonsten ein Fatal Error geworfen wurde. Zunächst habe ich das Plugin daher deaktiviert bzw. gelöscht, und später erneut installiert. Somit lief die Site wieder, das Einloggen war möglich und natürlich bestand der erste Schritt darin, das WPGDPR-Plugin zu aktualisieren.

Danach musste noch ein wenig aufgeräumt werden – BackWPup hatte sich selbst nicht mit gesichert, es handelte sich soweit ich mich erinnere, um eine Default-Einstellung, somit musste das Plugin auch erstmal wieder installiert werden. Die Konfiguration war jedoch noch vorhanden, einzig war eine Aktualisierung des FTP-Passworts notwendig, da ich dieses ja in einem der ersten Schritte geändert hatte.

Des Weiteren wurde der Datenbank-Dump nicht mehr benötigt, also raus damit aus dem Hauptverzeichnis sowie dem MariaDB-Mount.

Fazit

Insgesamt waren die Schritte zur Wiederherstellung jedoch problemlos auszuführen. Bis auf die Kleinigkeit mit den fehlenden config.php-Dateien funktionierte es auf Anhieb. BackWPup kann ich nur empfehlen, dies schließt insbesondere auch die freie Version mit ein. Andere Backup-Plugins sind teilweise sehr beschränkt in ihrer Funktionalität, falls man nicht eine “Pro”-Version kauft, BackWPup jedoch beinhaltet sämtliche Features, um ein Backup vollständig anzulegen. In der ebenfalls verfügbaren und kostenpflichtigen “Pro”-Version sind darüber hinaus Funktionen zur automatischen Wiederherstellung vorhanden, natürlich beinhaltet die Pro-Variante einige erweiterte Features wie eine größere Auswahl an Storage-Optionen, Verschlüsselung der Backup-Dateien usw., und zu guter Letzt Support. Einziges Manko ist der Preis, für mich lohnt es sich aktuell nicht, hier zu investieren, da die kostenfreie Version bereits alles bietet, was ich benötige und es letztlich auch irrelevant ist, wenn dieses Blog vielleicht mal für ein paar Stunden nicht erreichbar ist. Für den kommerziellen Einsatz würde ich jedoch keine Sekunde zögern, die Pro-Version von BackWPup zu kaufen, denn wie man sieht, kann ein Backup einem sprichwörtlich den Allerwertesten retten.

Ebenfalls bin ich recht froh über die Docker-Variante dieser WordPress-Installation. Zwar bietet auch ein Docker-Container keinen hundertprozentigen Schutz, aber letztlich fühlt es sich doch besser an, den kompletten Container, die zugrunde liegenden Images und alles, was dazu gehört, einfach mal löschen zu können, falls der Verdacht besteht, dass eine Manipulation hätte stattfinden können. Bei einem Angriff via Webshell wäre der Angreifer somit zunächst innerhalb des PHP-Containers gelandet und hätte noch eine weitere Schicht durchdringen müssen, um zum Hostsystem zu gelangen.

Hatte ich eigentlich erwähnt, wie wichtig Backups sind..?

 

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Tags:
Kategorien: Netzkultur Technologie