← AEU Hosting Blog

Elementor-CSRF-Schwachstelle macht aus einem geklickten Link ein Admin-Konto

2026-10-08

Elementor-CSRF-Schwachstelle macht aus einem geklickten Link ein Admin-Konto

Eine Cross-Site-Request-Forgery-Schwachstelle (CSRF) im Elementor Website Builder Plugin ermöglicht es, dass ein einziger Link, der von einem eingeloggten WordPress-Benutzer geöffnet wird, diesen Benutzer jede REST-API-Aktion ausführen lässt, die sein Konto ausführen darf. Auf einer Standard-WordPress-Installation erstellt ein Administrator, der den Link anklickt, ein zweites Administratorkonto für den Angreifer. Die Schwachstelle betrifft genau die Versionen 4.3.0 und 4.3.1 und nur diese beiden Versionen. Sie wurde vom Sicherheitsforscher Saggre entdeckt und an Patchstack gemeldet, und Patchstack hat Abwehrregeln zum Schutz vor Ausnutzung herausgegeben. Die Schwachstelle hat einen CVSS-Score von 8,8 und liegt damit im hohen Schweregradbereich.

Elementor ist der am weitesten verbreitete Page Builder für WordPress und auf über zehn Millionen Websites aktiv. Er bietet einen visuellen Drag-and-Drop-Editor, eine Vorlagenbibliothek und einen Theme-Builder zum Erstellen von Seiten ohne Code. Der betroffene Code gehört zum Editor Events Modul, das die Editor-Telemetrie von Elementor weiterleitet. Dieses Modul ist hinter einem Experiment verborgen, aber nicht auf eine Weise, die die meisten Website-Betreiber sehen oder beeinflussen können. Das Experiment ist als versteckt markiert, sodass es überhaupt nicht auf dem Experimente-Bildschirm von Elementor erscheint, und seine default_active-Einstellung aktiviert es für jede Website, deren erste Elementor-Installation Version 3.32.0 oder höher war. Eine Standardinstallation von 4.3.0 oder 4.3.1 ohne geänderte Einstellungen und ohne weitere Plugins ist betroffen. Der Konstruktor des Moduls registriert außerdem den relevanten Filter bedingungslos, sodass nichts an den Telemetrie-Einstellungen einer Website die Schwachstelle verhindert. Versionen vor 4.3.0 enthalten den Editor Events Proxy überhaupt nicht und sind nicht betroffen.

Der Events-Proxy registriert zwei REST-Routen und möchte, dass seine eigenen Anfragen von der REST-Nonce-Prüfung ausgenommen werden, dem eingebauten Schutz von WordPress Core gegen CSRF. Dazu hängt er den Filter rest_authentication_errors mit Priorität 0 ein. Das Problem ist das Timing: Dieser Filter läuft, bevor WordPress eine Route zugeordnet hat, sodass der Callback nur die rohe Anfrage-URI-Zeichenkette prüfen kann. Der Code verwendet eine unverankerte strpos()-Suche über die gesamte $_SERVER['REQUEST_URI'], die sowohl den Pfad als auch die Query-String enthält. Da die Query-String von demjenigen geschrieben wird, der den Link erstellt, kann sich jede REST-Anfrage selbst von der Nonce-Prüfung befreien, indem sie einen harmlos aussehenden Parameter anhängt, der die wörtliche Zeichenkette elementor/v1/events/ enthält. Zum Beispiel erfüllen alle folgenden die Prüfung, während die Anfrage tatsächlich an einen völlig anderen Endpunkt gesendet wird: /wp-json/wp/v2/users?zzz=elementor/v1/events/, /wp-json/wp/v2/users?elementor/v1/events/ (ohne Parameternamen) und /wp-json/wp/v2/users?q=foo-elementor/v1/events/-bar (nicht einmal ein ganzes Segment).

Von diesem Filter true zurückzugeben ist stärker als nur eine Prüfung zu überspringen. Der Filter rest_authentication_errors ist ein gemeinsamer Kanal, und jeder gut funktionierende Handler darauf beginnt damit, zu prüfen, ob ein früherer Handler bereits eine Entscheidung getroffen hat. Die eigene Nonce-Prüfung von WordPress Core ist genau so geschrieben: Sie kehrt sofort zurück, wenn ein vorheriger Filter einen nicht-leeren Wert zurückgegeben hat. Da der Filter von Elementor mit Priorität 0 läuft und true zurückgibt, behauptet er, dass die Authentifizierung bereits erfolgreich war, bevor irgendjemand anderes etwas sagen kann. Die Nonce-Verifizierung von Core wird nie erreicht, und jedes Sicherheits-Plugin, das die REST-Authentifizierung über denselben Filter härtet, wird ebenfalls übersprungen. Was bleibt, ist der permission_callback der Route, der fragt, was der aktuelle Benutzer tun darf. Da das Opfer eingeloggt ist, beantwortet sein Cookie diese Frage großzügig. Die Autorisierung bleibt bestehen; nur der Nachweis der Absicht fehlt.

Die meisten REST-CSRF-Funde benötigen eine Seite, die ein Formular absendet oder eine fetch()-Anfrage ausführt, was die Zustellung auf Orte beschränkt, an denen der Angreifer Skript oder Markup platzieren kann. Dies hier nicht, da WordPress Core einen _method-Query-Parameter akzeptiert, der das HTTP-Verb überschreibt. Eine einfache GET-Navigation, wie das Klicken auf einen einfachen Link, reicht aus, um einen Schreibvorgang auszuführen. Der gesamte Angriff passt in eine URL: https://example.com/wp-json/wp/v2/users?_method=POST&username=csrfadmin&email=csrfadmin%40example.test&password=...&roles%5B%5D=administrator&x=elementor/v1/events/. Ohne den letzten Parameter gibt dieselbe Anfrage rest_cannot_create_user mit HTTP 401 zurück. Mit ihm gibt der Server HTTP 201 und ein Benutzerobjekt zurück, dessen roles-Array ["administrator"] ist. Der Forscher bestätigte, dass ein Marker, der ein Zeichen kürzer als der echte Namespace ist, elementor/v1/event/, abgelehnt wird, was jede andere Erklärung für den Unterschied ausschließt. Da ein einzelnes Anchor-Tag ausreicht, kann die Payload überall dort zugestellt werden, wo ein Link hingehen kann: eine E-Mail, eine Chat-Nachricht, ein Forumsbeitrag, ein Kommentar auf einer nicht verwandten Website. Das Opfer sieht einen normalen Link und eine JSON-Antwort.

Der Explosionsradius ist jede REST-Route. Dies ist keine Schwachstelle in Elementors eigenen Endpunkten, die zufällig per CSRF erreichbar ist. Die Umgehung wird vor dem Routing ausgewertet und gilt daher für die gesamte REST-API-Oberfläche der Website: WordPress-Core-Routen und die Routen jedes anderen Plugins, das daneben installiert ist. Das Erstellen eines Administrators über /wp/v2/users ist die klarste Demonstration, aber der Forscher zeigte auch, dass GET /wp-json/wp/v2/settings von HTTP 401 auf HTTP 200 wechselt und die Website-Einstellungen im Antworttext zurückgegeben werden. Alles, was das Konto des Opfers über REST erreichen kann, ist betroffen, einschließlich Endpunkte von Plugins, die nichts falsch gemacht haben.

Elementor hat die Schwachstelle in Version 4.3.2 behoben. Der Ersatzcode liest $wp->query_vars['rest_route'] anstelle der rohen URI. Dieser Wert ist die Route, die WordPress tatsächlich aufgelöst hat, nach dem Umschreiben, wobei die Query-String bereits abgetrennt ist. Es gibt keinen vom Angreifer zusammengestellten Text mehr in dem zu testenden Wert. Der Vergleich änderte sich auch von false !== strpos(...) zu 0 === strpos(...), sodass der Namespace am Anfang der Route erscheinen muss und nicht irgendwo darin. Diese zweite Änderung ist entscheidend: Sie zu überspringen hätte eine kleinere Version desselben Fehlers hinterlassen, da eine Route wie /otherplugin/v1/x/elementor/v1/events/ immer noch übereingestimmt hätte. Ein hinzugefügter is_string()-Guard schließt eine weitere Tür, bei der rest_route als Array übermittelt werden könnte.

Die Ursache ist eine Diskrepanz zwischen der Frage, die der Code stellte, und den Daten, die zur Beantwortung verfügbar waren. Der Code wollte wissen: "Ist diese Anfrage für meine Route?", aber er fragte zu einem Zeitpunkt, an dem WordPress dies noch nicht entschieden hatte, und begnügte sich mit einer Teilstring-Suche über eine Zeichenkette, die der Client kontrolliert. Zwei Lehren verallgemeinern sich über dieses Plugin hinaus. Erstens ist $_SERVER['REQUEST_URI'] vom Angreifer kontrollierte Eingabe, keine Routing-Metadaten; jede Sicherheitsentscheidung, die darauf basiert, muss die Query-String entfernen und den Vergleich verankern. Zweitens ist rest_authentication_errors ein gemeinsamer Kanal, und einen truthy-Wert zurückzugeben ist kein lokales Opt-out. Es behauptet Erfolg gegenüber jedem nachgelagerten Handler, einschließlich der Nonce-Verifizierung von WordPress Core. Ein Filter, der nur "keine Meinung" sagen muss, sollte $result unverändert zurückgeben. Patchstack empfiehlt dringend, Elementor auf Version 4.3.2 oder höher zu aktualisieren. Der Zeitplan ist kurz: Der Bericht ging am 22.09.2026 ein, Elementor veröffentlichte Version 4.3.2 am 24.09.2026, und die öffentliche Warnung wurde am 25.09.2026 veröffentlicht. Für Website-Betreiber, die nicht jede Plugin-Veröffentlichung selbst überwachen können, reduziert verwaltetes WordPress-Hosting mit automatischen Backups und Sicherheitshärtung, wie AEU Hosting, den Schaden, wenn ein anfälliges Plugin ausgenutzt wird, und hilft, schnell eine saubere Kopie wiederherzustellen.