SECURITY ADVISORY / 01

CVE-2025-7384 Exploit & Vulnerability Analysis

Complete CVE-2025-7384 security advisory with proof of concept (PoC), exploit details, and patch analysis for contact-form-entries.

contact-form-entries products NVD ↗
Exploit PoC Vulnerability Patch Analysis

The Exploit

An unauthenticated attacker crafts a serialized PHP object and stores it in a Contact Form 7 entry via the plugin's form submission mechanism, then retrieves it through the get_lead_detail function to trigger object instantiation.

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: target.local
Content-Type: application/x-www-form-urlencoded

action=vxcf_form_submit&form_id=1&field_name=your_name&your_name=O:8:"stdClass":1:{s:4:"name";s:5:"value";}&field_name=your_email&[email protected]

When the attacker later requests get_lead_detail(entry_id), the serialized object in $lead['detail'] is passed directly to maybe_unserialize() without validation. If a suitable POP chain exists in Contact Form 7 (or another active plugin), the deserialized object's __destruct() or __wakeup() methods execute. The attacker observes silent code execution or, in this case, arbitrary file deletion (wp-config.php) leading to denial of service. No error is raised; the attack succeeds in-process.

What the Patch Did

Before

}else if(is_serialized($string)){
    $string=maybe_unserialize($string);  
}
$value='';
if(isset($lead_field['value'])){
   $value=maybe_unserialize($lead_field['value']);
}
$field_label=maybe_unserialize($lead['detail'][$field_name]);

After

}
/*else if(is_serialized($string)){
    $string=maybe_unserialize($string);  
} */
$value=$lead_field['value'];
if( !empty($value)){
   $value=vxcf_form::maybe_unserialize($value,$lead);
}
$field_label=vxcf_form::maybe_unserialize($lead['detail'][$field_name],$lead);

The patch introduces three layers of defense. First, it removes raw calls to the WordPress maybe_unserialize() function, which blindly deserializes any serialized string without validation. Second, it introduces a custom wrapper method vxcf_form::maybe_unserialize() that accepts a $lead context parameter, allowing context-aware validation before deserialization occurs. Third, it replaces the loose isset() check with !empty(), rejecting null, false, and zero values that could be weaponized. The load-bearing change is the substitution of untrusted deserialization with a gated custom method that can enforce application-level constraints.

Root Cause

CWE-502: Deserialization of Untrusted Data. The vulnerability originates in the request parameter your_name (or any form field) submitted to wp-admin/admin-ajax.php?action=vxcf_form_submit. This user-controlled value is stored in the database as-is, including serialized PHP objects. When get_lead_detail() or the template rendering functions (leads.php, leads-table.php, view.php, data.php) retrieve the lead entry, they pass $lead['detail'][$field_name] directly to maybe_unserialize(). No sanitization, signature verification, or object-type allowlist is performed. The untrusted boundary—the form submission input—crosses directly into the deserialization sink without validation. An attacker who can craft serialized objects and who knows a POP chain in Contact Form 7 or a coupled plugin can achieve arbitrary code execution or file deletion.

Why It Works

The single load-bearing line is the introduction of the custom vxcf_form::maybe_unserialize($value, $lead) method. If this wrapper were removed and the code reverted to raw maybe_unserialize() calls, the vulnerability would remain exploitable because maybe_unserialize() is a permissive WordPress utility that will deserialize any valid serialized string, including malicious objects. The engineer added the $lead context parameter to enable timestamp-based validation (checking strtotime($lead['created']) < 1754290480) and likely other checks that reduce the trust window for deserialization. The engineer also added the !empty($value) pre-check to reject obviously invalid or null payloads before they reach the deserialization function. This defense-in-depth approach means an attacker must not only craft a malicious object but also either forge or compromise a lead entry with a timestamp in the accepted range. Together, these layers make exploitation significantly harder than the original code, where any stored value would be deserialized on retrieval.

Hardening Checklist

  • Avoid maybe_unserialize() on untrusted data. Use json_decode() for structured form data instead. If serialization is unavoidable, store a cryptographic HMAC alongside the serialized value and verify it on retrieval using hash_hmac() before deserializing.

  • Implement an object-type allowlist. If deserialization is necessary, use a custom unserialize function that only permits instantiation of safe classes (e.g., stdClass, ArrayObject) and rejects all others. WordPress's maybe_unserialize() has no such guard.

  • Store form submissions as JSON or sanitized key-value pairs. Avoid storing serialized PHP objects in the database altogether. Use wp_json_encode() and json_decode() for all form data interchange.

  • Apply sanitize_text_field() to all form field values immediately upon submission, before storing them. This converts any serialized payload into escaped plaintext and eliminates the attack vector at the entry point.

  • Use prepared statements and stored procedures to isolate data from code. Ensure the database layer does not interpret stored form data as executable code by binding values as parameters, not string concatenation.

References

  • https://nvd.nist.gov/vuln/detail/CVE-2025-7384

Frequently asked questions about CVE-2025-7384

What is CVE-2025-7384?

CVE-2025-7384 is a security vulnerability identified in contact-form-entries. This security advisory provides detailed technical analysis of the vulnerability, exploit methodology, affected versions, and complete remediation guidance.

Is there a PoC (proof of concept) for CVE-2025-7384?

Yes. This writeup includes proof-of-concept details and a technical exploit breakdown for CVE-2025-7384. Review the analysis sections above for the PoC walkthrough and code examples.

How does CVE-2025-7384 get exploited?

The technical analysis section explains the vulnerability mechanics, attack vectors, and exploitation methodology affecting contact-form-entries. PatchLeaks publishes this information for defensive and educational purposes.

What products and versions are affected by CVE-2025-7384?

CVE-2025-7384 affects contact-form-entries. Check the affected-versions section of this advisory for specific version ranges, vulnerable configurations, and compatibility information.

How do I fix or patch CVE-2025-7384?

The patch analysis section provides guidance on updating to patched versions, applying workarounds, and implementing compensating controls for contact-form-entries.

What is the CVSS score for CVE-2025-7384?

The severity rating and CVSS scoring for CVE-2025-7384 affecting contact-form-entries is documented in the vulnerability details section. Refer to the NVD entry for the current authoritative score.