WordPress-XSS-Kampagne richtet vier Zugangswege zurück in Websites ein
Eine WordPress-XSS-Kampagne nutzt Schwachstellen in zwei voneinander unabhängigen Plugins aus, um schädliches JavaScript auszuführen, wenn ein Administrator gespeicherte Kundendaten anzeigt. Patchstack beobachtete die Aktivität erstmals am 4. Oktober 2026, zunächst gegen CVE-2026-93836 in WPC Product Bundles for WooCommerce und anschließend am 5. Oktober gegen CVE-2026-94504 in Ninja Forms. Beide Angriffe laden dasselbe Script von imgcdn1.com, das danach die aktive Sitzung des Administrators nutzt, um Malware zu installieren und vier separate Zugangswege zurück in die Website einzurichten. Laut Patchstack findet eine aktive Ausnutzung statt, sie ist in den Telemetriedaten des Unternehmens jedoch weiterhin nur in begrenztem Umfang sichtbar. Zudem sollten die beiden bestätigten Schwachstellen zur Auslieferung nicht als endgültige Gesamtzahl betrachtet werden.
Bei beiden Schwachstellen handelt es sich um unauthenticated stored cross-site scripting, kurz stored XSS. Das bedeutet, dass ein Angreifer schädlichen Browsercode auf einer Website speichern kann, ohne sich anzumelden, und anschließend wartet, bis dieser Code ausgeführt wird, wenn ein Administrator den betroffenen record öffnet. CVE-2026-93836 betrifft WPC Product Bundles for WooCommerce bis einschließlich Version 8.6.6 und hat einen CVSS-Schweregrad von 7.1. Angreifer übermittelten über den Parameter woosb_ids[…][qty] eine Mengenangabe, die mit einer gültigen Zahl begann, gefolgt von einem Script-Element. Der Wert bestand die Validierung, blieb in den Bestellmetadaten von WooCommerce gespeichert und wurde später ohne ausreichenden Schutz angezeigt. Das Plugin hat mehr als 30.000 aktive Installationen, und sein Changelog nennt Version 8.6.7 als Sicherheitskorrektur.
CVE-2026-94504, ebenfalls mit CVSS 7.1 bewertet, betrifft Ninja Forms bis einschließlich Version 3.15.3, ein Plugin mit mehr als 500.000 aktiven Installationen. Der reguläre AJAX-Endpunkt für Übermittlungen akzeptierte von Angreifern kontrollierte Inhalte in textarea-Feldern ohne rich-text. Der ältere administrative Editor für Übermittlungen konnte diese Inhalte anschließend anzeigen, ohne sie sicher zu codieren, sodass JavaScript ausgeführt werden konnte, wenn die Übermittlung angezeigt wurde. Version 3.15.4 verstärkte das output escaping auf diesem Bildschirm. Obwohl die eingeschleusten Loader an die unterschiedlichen Formular- und Bestellkontexte angepasst waren, riefen beide den zentralen payload unter https://imgcdn1.com/fz/x.js ab.
Die Analyse von Patchstack ergab, dass x.js ein 19.378 Byte großes post-exploitation script ist, also Code, der eingesetzt wird, nachdem der erste Zugriff bereits erlangt wurde. Es stiehlt weder das Cookie des Administrators noch benötigt es eine weitere Server-Schwachstelle. Da es im browser context der kompromittierten Website ausgeführt wird, enthalten Anfragen an wp-admin automatisch die authentifizierte Sitzung des Administrators. Das Script öffnet privilegierte Seiten, extrahiert CSRF nonces – temporäre Werte, mit denen WordPress administrative Aktionen bestätigt – und übermittelt diese Werte über legitime WordPress-Funktionen. Der Schutz durch HttpOnly cookies verhindert dies nicht, weil der Code das Cookie nie direkt auslesen muss.
Bevor x.js Änderungen vornimmt, kontaktiert es unter imgcdn1.com/fz/c.php den command-and-control server, kurz C2, und übermittelt die Adresse der Zielwebsite. Die Antwort gibt an, ob die Plugin-, Administrator- und zusätzlichen persistence-Phasen erfolgreich waren. Das Script zeichnet den Fortschritt außerdem im Local Storage des Browsers unter einem key auf, der mit __xp_v9_ beginnt, und markiert die Phasen als plugin, admin, emer und schließlich all. Es meldet die Ergebnisse über fetch(), sendBeacon() oder eine Bildanfrage, sodass die Statusmeldung mehrere Möglichkeiten hat, eine Seitennavigation zu überstehen.
Mithilfe der Sitzung des Administrators öffnet die Malware die WordPress-Seite zum Hochladen von Plugins, erfasst deren nonce und lädt ein ZIP-Paket vom C2 herunter. Das Paket wird als wp-smart-thumbnails installiert und gibt sich als „WP Smart Thumbnails“ 1.2.4 von „MediaPress Labs“ aus. Zu seinen vier Dateien gehören der 20.728 Byte große Dropper wp-smart-thumbnails.php, der 14.330 Byte große persistence installer emer-run.php und zwei winzige Attrappen. Alle tragen Zeitstempel vom Juli 2026 und sind damit älter als die Kampagne. Die Hauptdatei beendet sich, wenn WordPress sie regulär lädt, und wird nur über eine direkte Webanfrage ausgeführt, wodurch sie im Dashboard inaktiv wirken kann.
Der Dropper verbirgt seinen payload hinter sieben Transformationen mit Base64, XOR, Umkehrung, ROT13, Byte-Rotation und Dekomprimierung, gefolgt von einem MD5 integrity check. Statt die häufig erkannte Funktion eval() zu verwenden, registriert er den stream wrapper dyiv:// und bindet den decodierten Code über diese Adresse ein. Das Ergebnis ist ein etwa 37 KB großer grafischer Dateimanager mit dem Titel „Moon, tell me if I could“. Er benötigt weder Passwort noch token oder WordPress-Berechtigung und kann über ein JSON interface Dateien auflisten, hochladen, löschen, umbenennen, erstellen, lesen und speichern. Er ruft system() oder exec() nicht direkt auf, doch seine Fähigkeit, von Angreifern kontrollierte Dateien an jeden beschreibbaren Speicherort zu schreiben, reicht aus, um eine weitere webshell zu installieren – ein über das Web erreichbares Werkzeug zur Kontrolle von Dateien oder zur Ausführung zusätzlichen schädlichen Codes.
Die Komponente emer-run.php richtet den dauerhafteren Zugriff ein. Zunächst fügt sie ein Konto mit vollständigen Berechtigungen hinzu. Dessen unauffällig wirkender Benutzername wird aus Wörtern wie support, updater, maintenance oder backup ausgewählt; hinzu kommen eine E-Mail-Adresse mit @wordpress.org und ein zufälliges Passwort mit 16 Zeichen. Anschließend schreibt die Komponente ein must-use plugin, eine WordPress-Erweiterung, die automatisch geladen wird und nicht über den normalen Plugins-Bildschirm deaktiviert werden kann. Hooks in dieser Datei entfernen das Konto aus user queries, Administratorfiltern und angezeigten Gesamtzahlen, sodass es unter Benutzer nicht erscheint und nicht mitgezählt wird. Durch das Entfernen des Plugins wp-smart-thumbnails wird dieser versteckte Administrator nicht entfernt.
Ein zweites must-use plugin erstellt /wp-login.php?_wplogin=. Jeder, der über ein gültiges token verfügt, wird unbemerkt als ältester bestehender Administrator der Website authentifiziert – normalerweise als ursprünglicher Eigentümer – und nicht als das versteckte Konto. Logs, die nur die Benutzer-ID erfassen, können die Sitzung daher echt erscheinen lassen. Beide als must-use plugin installierten Dateien sind auf jeder infizierten Website mit einem anderen key und zufälligen Variablennamen verschleiert, sodass nicht jede Kopie anhand eines einzigen file hash erkannt werden kann. Der Installer ermittelt außerdem die älteste Änderungszeit im WordPress root und überträgt sie auf die neuen Dateien, wodurch Suchverfahren umgangen werden, die nur nach kürzlich vorgenommenen Änderungen suchen.
Eine einzige erfolgreiche Ausführung hinterlässt somit vier voneinander unabhängige Zugriffsmethoden: einen sichtbaren Administrator, der mit Zugangsdaten vom C2 erstellt wurde, den verborgenen Administrator, die spezielle Anmelde-URL für den ältesten Administrator und den Dateimanager ohne Authentifizierung. Nur die erste Methode ist normalerweise in WordPress sichtbar. stored XSS ist hier besonders effektiv, weil der Angreifer keinen Administrator dazu bringen muss, einen speziellen Link zu öffnen. Der payload wartet innerhalb einer gewöhnlichen Bestellung oder Formularübermittlung. WordPress 7.1.1 behob im September 2026 ein separates unauthenticated stored XSS-Problem in wpautop(), was zeigt, dass dieses Angriffsmodell nicht auf ein einziges Plugin beschränkt ist.
Die Domain imgcdn1.com hostete das Browser-Implantat, die Prüfungen der Opfer, das schädliche Plugin-Paket, die vom Angreifer ausgewählten Zugangsdaten und die Berichte über Kompromittierungen. Sie wurde am 1. Oktober registriert, am 2. Oktober an einen Cloudflare nameserver delegiert und erschien erstmals am 4. Oktober um 10:39 UTC in den Telemetriedaten von Patchstack. Die beiden Plugin-Schwachstellen waren am 22. September öffentlich bekannt gegeben worden.