
Ein Proof-of-Concept-Fuzzer für WordPress-Plugins
Ein Proof-of-Concept WordPress-Plugin-Fuzzer, der zur Entdeckung von mehr als 300 Schwachstellen in WordPress-Plugins führte, die auf fast 30 Millionen Websites installiert sind.
Die verwendete Technik wird unter https://kazet.cc/2022/02/03/fuzzing-wordpress-plugins.html beschrieben.
Wenn du die Forschung fortsetzen möchtest, beginne mit weniger populären Plugins – wenn ein Plugin zwischen Oktober 2021 und Januar 2024 mindestens 10.000 aktive Installationen erreicht hat, habe ich die Fuzzer-Berichte höchstwahrscheinlich angesehen (und der Fokus lag auf Plugins mit mindestens 20.000 aktiven Installationen). Da der Fuzzer stark zufallsbasiert arbeitet, bleiben einige Schwachstellen in diesen Plugins unentdeckt – aber weniger.
Fuzzer-Berichte enthalten viele False Positives – die meisten deuten nicht auf eine Schwachstelle hin. Analysiere nach einem Bericht zunächst, ob das beobachtete Verhalten tatsächlich eine Schwachstelle oder ein False Positive ist. Spamme WPScan/Hersteller nicht mit rohen Fuzzer-Berichten zu – liefere stattdessen einen PoC-Exploit.
Aus offensichtlichen Gründen enthalten die Beispiele nur Schwachstellen, die bereits behoben wurden.
Angenommen, du fuzzest responsive-vector-maps in Version 6.4.0:
./bin/fuzz_object plugin responsive-vector-maps --version 6.4.0
(um die neueste Version zu fuzzen, lasse --version weg).
Nach dem Fuzzing (das für dieses Plugin 10-30 Minuten dauert) kannst du aufrufen:
./bin/print_findings data/object_fuzz_results/
Du siehst unter anderem:
.
Das bedeutet, dass der Fuzzer die Ausführung von fopen() auf einem bekannten Payload erkannt hat.
Die meisten Payloads enthalten das Wort GARLIC, um die automatische Erkennung in der Ausgabe zu erleichtern.
Du kannst sie in docker_image/magic_payloads.php sehen oder konfigurieren.
Dann kannst du den Quellcode durchsuchen und feststellen, dass der Endpunkt wp_ajax_rvm_import_markers
tatsächlich den Dateiinhalt zur Ausgabe nutzt, sodass du beliebige Dateien auf dem Server lesen kannst: CVE-2021-24947.
Was du in Weiß siehst, ist ein als interessant betrachteter Crash (du kannst sie in crash_detectors.py ändern oder neue hinzufügen). Grün ist der Kontext. In Blau siehst du den Berichtsdateinamen (mit Plugin-Name), Plugin-Popularität und Endpunkt-Name (hier: der AJAX-Action-Name).
Die gelben Daten zeigen, welche Payloads in welche Variablen injiziert wurden.
Angenommen, du fuzzest page-builder-add in Version 1.4.9.4:
./bin/fuzz_object plugin page-builder-add --version 1.4.9.4
Nach dem Ausdrucken der Ergebnisse siehst du bekannte Payloads zurückgespiegelt:
.
Du kannst dann manuell testen, ob diese Stelle (denke daran: in Blau siehst du den Endpunkt-Name, hier: der Menüseitenname) tatsächlich anfällig für XSS ist. In diesem Fall ist sie es: CVE-2021-25067.
./bin/fuzz_object plugin duplicate-page-or-post --version 1.4.6
Nach dem Ausdrucken der Ergebnisse siehst du, dass update_option aufgerufen wird:
.
Die Analyse des Codes des Endpunkts zeigt dir, dass dies tatsächlich zu einer gespeicherten XSS-Schwachstelle führt: CVE-2021-25075.
Leider findet der Fuzzer bei den meisten Plugins keine interessanten Crashes, und bei den restlichen sind die meisten Berichte False Positives. Wenn du zum Beispiel siehst:
Call: wp_mail arguments={'to': '[email protected]', 'subject': '[Plugin contact] - http://GARLICGARLICGARLIC.example.com'}
Kann das bedeuten, dass wp_mail zwar aufgerufen wird, du aber den Empfänger und den Großteil des Betreffs nicht kontrollierst. Wenn du sicher sein willst, schau dir den Plugin-Quellcode an.
__GARLIC_ACCESSED__ _FILES[files] __ENDGARLIC__ siehst – bedeutet das, dass der Zugriff auf eine hochgeladene
Datei erkannt wurde. Es werden derzeit keine weiteren Prüfungen durchgeführt – um zu prüfen, ob dies eine
Schwachstelle ist, sieh dir den Code an.$_GET['page'] injizieren, wenn eine bestimmte Menüseite angezeigt werden soll.Der erste Lauf des Fuzzings oder der Tests kann etwa eine Stunde dauern, da wir das Docker-Image mit instrumentiertem PHP und WordPress erstellen müssen.
./bin/fuzz_object plugin PLUGIN_SLUG
./bin/fuzz_object theme THEME_SLUG
Du kannst auch ein Plugin aus einer lokalen Zip-Datei installieren:
./bin/fuzz_object plugin PLUGIN_FILE_NAME.zip
Um die vom Fuzzer gefundenen Ergebnisse auszudrucken, verwende:
./bin/print_findings data/object_fuzz_results/
Um die Tests auszuführen, verwende:
./bin/test
Warnung: Die Tests dauern lange (mehr als eine Stunde) und da sie prüfen, ob der Fuzzer Schwachstellen finden würde, schlagen sie mit einer gewissen Wahrscheinlichkeit fehl.
wpgarlic verwendet pre-commit, um Linter auszuführen und den Code zu formatieren.
pre-commit wird in CI ausgeführt, um sicherzustellen, dass der Code korrekt formatiert ist.
Um es lokal auszuführen, verwende:
pre-commit run --all-files
Um pre-commit so einzurichten, dass es vor jedem Commit ausgeführt wird, verwende:
pre-commit install
Du kannst eine Testumgebung mit nur einem installierten Plugin starten mit:
./bin/manual_testing PLUGIN_SLUG|PLUGIN_PATH.zip [version]
Du kannst ein Plugin über seinen Slug oder aus einer lokalen Zip-Datei installieren.
Es wird unter http://127.0.0.1:8001/ lauschen.
Es gibt zwei Testbenutzer in der Datenbank:
Dieses Tool ist ein Proof-of-Concept – dieser Abschnitt enthält Stellen, an denen es verbessert werden kann, um mehr Schwachstellen zu finden.
Du möchtest vielleicht filtering.py bearbeiten – es enthält die Regeln, die einen bestimmten Crash als wichtig
oder unwichtig einstufen. Wenn du sie änderst, hast du möglicherweise mehr False Positives, findest aber auch mehr
Schwachstellen. Zum Beispiel ist der einzige Header, den ich als interessant betrachte, wenn er ausgegeben wird, der Location-Header,
um Open-Redirect-Schwachstellen zu erkennen. Das ist nur eine Idee, und du hast vielleicht andere.
Eine weitere Datei, die es wert ist, erweitert zu werden, ist docker_image/patch_wordpress.sh. Sie beschreibt,
welche Funktionsaufrufe als interessant protokolliert werden.
Wenn du andere Payloads injizieren möchtest (oder die Wahrscheinlichkeiten ihrer Injektion ändern möchtest),
bearbeite docker_image/magic_payloads.php und docker_image/fuzz/config.py.
crash_detector.py enthält reguläre Ausdrücke, die interessante Crashes oder interessante Informationen
(z. B. E-Mails) finden, die offengelegt werden.
Das Fuzzing von REST-Routen als eingeloggter Admin wurde deaktiviert, da es zu False Positives führte.
Entkommentiere rest_routes_admin in config.DEFAULT_ENABLED_FEATURES, um das zu ändern.
Einige Plugins benötigen andere (z. B. woocommerce) als Abhängigkeit. Wenn du ein Plugin mit einer Abhängigkeit fuzzest, möchten wir nur das ausgewählte Plugin fuzzen und die AJAX-Aktionen, REST-Routen und Menüseiten der Abhängigkeit überspringen. Wir möchten woocommerce-Aktionen/Routen/Seiten nur dann fuzzen, wenn wir woocommerce zum Fuzzen ausgewählt haben.
Listen von Abhängigkeitsaktionen/Routen/Seiten werden Blocklisten genannt und sind in docker_image/blocklists/ aufgeführt.
Dateien mit dem Namen common enthalten die WordPress-Kernaktionen/Routen/Seiten – auch diese wollen wir nicht fuzzen.
Um diese Blocklisten zu aktualisieren, verwende ./bin/update_blocklists.
Vielleicht. Installiere das Plugin in einer lokalen Testumgebung (zum Beispiel kannst du die im Abschnitt Manuelle Testumgebung beschriebene verwenden) und analysiere den Fehler.
Gehe nicht davon aus. Der Fuzzer findet einige Klassen von Schwachstellen, hat aber seine Grenzen.
Der Fuzzer findet für die meisten Plugins nichts – der Zweck des Tools ist eher das massenhafte Scannen einer großen Anzahl von WordPress-Plugins, nicht die umfassende Prüfung eines einzelnen Plugins.
Das ist möglich. Der Fuzzer wählt Payloads zufällig aus und führt an anderen Stellen Zufälligkeit ein (z. B.
wie sich der ==-Operator in den unter https://kazet.cc/2022/02/03/fuzzing-wordpress-plugins.html#patched-equality beschriebenen Fällen verhalten soll).
Erstelle ein Github-Ticket oder sende mir eine E-Mail: [email protected].