Skip to content
KitploitKITPLOIT
ToolsBlog
Log in
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-7384 — Exploit PoC and root-cause analysis for a critical unauthenticated PHP object injection in WordPress Database for Contact Form 7, leading to RCE via arbitrary file deletion. | Kitploit
Tools/GitHubGitHub/dungsocool/cve-2025-7384
Vulnerability AnalysisExploitationWeb Application ExploitationLearning & EducationLabs & Practice
GitHubdungsocool/cve-2025-7384

CVE-2025-7384

Exploit PoC and root-cause analysis for a critical unauthenticated PHP object injection in WordPress Database for Contact Form 7, leading to RCE via arbitrary file deletion.

View Repository
122 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-7384 — PHP Object Injection to RCE

Plugin: Database for Contact Form 7 (contact-form-entries) ≤ 1.4.3
CVSS: 9.8 (Critical)
CWE: CWE-502 — Deserialization of Untrusted Data
Authentication Requirement: None (Unauthenticated)
Impact: Remote Code Execution


Table of Contents

  1. Vulnerability Overview
  2. Related Concepts
  3. Root Cause Analysis (Source Code + Debug)
  4. Attack Chain
  5. Step-by-Step Reproduction (POC)
  6. Impact Assessment
  7. Remediation Measures

1. Vulnerability Overview

The "Database for Contact Form 7" plugin (slug: contact-form-entries) version 1.4.3 and below contains a PHP Object Injection vulnerability. When a WordPress administrator views a form record (entry) inside the admin panel, the plugin calls the function maybe_unserialize() directly on data submitted by an unauthenticated user via Contact Form 7, without controlling the list of allowed classes to instantiate.

An attacker does not need to log in — they only need to submit a regular contact form while inserting a serialized PHP object into any form field. This data is stored raw in the database. When an admin opens to view that entry, the deserialization function will instantiate an object of the attacker's choice, triggering magic methods like __destruct() or __wakeup() → executing arbitrary behavior depending on the POP gadgets available in the WordPress environment.

Severity Level: With a suitable POP gadget (for example, a class whose __destruct() method calls unlink()), an attacker can delete the wp-config.php file, reverting WordPress back to its initial installation screen → reinstalling with an administrator account controlled by the attacker → installing a plugin containing a webshell → achieving full Remote Code Execution (RCE) on the server.

AttributeValue
CVE IDCVE-2025-7384
CVSS Score9.8 (Critical)
CWECWE-502 — Deserialization of Untrusted Data
Affected Plugincontact-form-entries (Database for Contact Form 7) ≤ 1.4.3
Authentication RequirementNone — anyone submitting a CF7 form can inject payload
Trigger ConditionAdmin views the injected entry in the admin panel
Maximum ImpactUnauthenticated Remote Code Execution
Patched Version1.4.4+ (replaces unserialize with json_decode or allowed_classes: false)

2. Related Concepts

PHP Serialization / Deserialization

PHP uses serialize() to convert an object into a structured text string, and unserialize() to restore the object from that string. When unserialize() receives data from an untrusted source (e.g., user input), an attacker can construct an arbitrary object belonging to any class currently loaded in PHP memory at that moment.

PHP Magic Methods

Special methods that PHP automatically invokes during an object's lifecycle. Most important in this context:

  • __wakeup() — invoked immediately when an object is unserialized
  • __destruct() — invoked when an object is destroyed (goes out of scope, or request ends)
  • __toString() — invoked when an object is cast to a string

POP Chain (Property-Oriented Programming)

A technique of chaining multiple magic methods from existing classes within the application to construct a dangerous sequence of behaviors. The attacker does not write new code — they only manipulate the properties of existing objects so that when magic methods execute, they perform actions unintentional to the developers.

maybe_unserialize() in WordPress

A WordPress Core wrapper function. It calls is_serialized() to check if a string is serialized data — if true, it calls unserialize() to restore the object. Problem: this function does not pass the allowed_classes parameter (available since PHP 7.0) to limit which classes are permitted to instantiate.


3. Root Cause Analysis — Vulnerability Discovery from Source Code

Step 1: Finding Sink Points (Sink Hunting)

Start by grepping the entire plugin source code to locate deserialization functions — these are the most dangerous functions in PHP as they can lead to Object Injection:

grep -rn "unserialize" wp-src/wp-content/plugins/contact-form-entries/

image.png

The output reveals multiple call sites for maybe_unserialize(), most notably inside includes/data.php line 545 within the verify_val() function:

image 1.png

// 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;
}

Key Question: Where does the $string variable originate? If it comes from user input without filtering → this is a vulnerability.

Step 2: Backward Tracing — Where does the data come from?

Find where verify_val() is invoked. Trace backward in the same data.php file:

image 2.png

// 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 is precisely $v['value'] — values retrieved from the wp_vxcf_leads_detail database table. This function is called when an admin views the details of a form entry.

Next Question: Where does data inside wp_vxcf_leads_detail come from? Who writes it?

Step 3: Finding Data Write Points (Source)

From Step 2, we know data is pulled from the database. Next question: who writes data into it? Search for INSERT queries within data.php:

grep -rn "insert" wp-src/wp-content/plugins/contact-form-entries/includes/data.php

image 3.png

Open the create_lead() function code (lines 85-103) for details:

image 4.png

At lines 98-99, the value $v — which is the content of a form field (e.g., your-message) — is inserted directly into the database via $wpdb->insert(). The plugin hooks into Contact Form 7's wpcf7_before_send_mail event, so whenever a user submits a form, all fields are stored raw.

Additional check: the plugin does use sanitize_text_field() and sanitize_textarea_field() prior to saving, but these two functions only strip HTML tags and special HTML characters — a serialized payload like O:21:"VulnerableFileHandler":2:{...} contains no HTML tags and thus passes through entirely intact.

Download Tool