CVE-2026-49105

WP Zendesk for Contact Form 7, WPForms, Elementor, Formidable and Ninja Forms <= 1.1.4 - Unauthenticated PHP Object Injection

highDeserialization of Untrusted Data
8.1
CVSS Score
8.1
CVSS Score
high
Severity
1.1.5
Patched in
4d
Time to patch

Description

The WP Zendesk for Contact Form 7, WPForms, Elementor, Formidable and Ninja Forms plugin for WordPress is vulnerable to PHP Object Injection in versions up to, and including, 1.1.4 via deserialization of untrusted input. This makes it possible for unauthenticated attackers to inject a PHP Object. No known POP chain is present in the vulnerable software. If a POP chain is present via an additional plugin or theme installed on the target system, it could allow the attacker to delete arbitrary files, retrieve sensitive data, or execute code.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
None
Scope
Unchanged
High
Confidentiality
High
Integrity
High
Availability

Technical Details

Affected versions<=1.1.4
PublishedJune 5, 2026
Last updatedJune 8, 2026
Affected plugincf7-zendesk

What Changed in the Fix

Changes introduced in v1.1.5

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to verify and exploit a PHP Object Injection vulnerability in the **WP Zendesk for Contact Form 7** plugin. ## 1. Vulnerability Summary The plugin is vulnerable to **Unauthenticated PHP Object Injection** due to the insecure use of `unserialize()` on user-contr…

Show full research plan

This research plan outlines the steps to verify and exploit a PHP Object Injection vulnerability in the WP Zendesk for Contact Form 7 plugin.

1. Vulnerability Summary

The plugin is vulnerable to Unauthenticated PHP Object Injection due to the insecure use of unserialize() on user-controlled data. The vulnerability typically resides in the entry_created method within the includes/crmperks-cf.php file. This method is triggered during form submissions from integrated plugins (Contact Form 7, WPForms, etc.). The plugin fails to sanitize the vxcf_form_data (or similar vxcf_ prefixed) POST parameter before passing it to unserialize().

2. Attack Vector Analysis

  • Endpoint: The submission handlers for Contact Form 7, WPForms, or Elementor.
    • For Contact Form 7: POST /?rest_route=/contact-form-7/v1/contact-forms/[ID]/feedback or POST /wp-admin/admin-ajax.php (if using the legacy AJAX handler).
  • Vulnerable Parameter: vxcf_form_data (inferred from similar CRM Perks vulnerabilities).
  • Authentication: Unauthenticated.
  • Preconditions:
    1. The plugin must be active.
    2. At least one form (e.g., Contact Form 7) must be created and accessible on the frontend.
    3. The plugin must be "hooked" into the form (default behavior).

3. Code Flow

  1. Entry Point: A user submits a form. For Contact Form 7, this triggers the wpcf7_before_send_mail hook.
  2. Plugin Callback: vxcf_zendesk::setup_main registers create_entry_cf as a callback for that hook.
  3. Method Execution: create_entry_cf calls $this->entry_created($lead, '0', $form_arr).
  4. Vulnerable Sink: Inside entry_created (located in includes/crmperks-cf.php), the plugin checks for the presence of a specific POST parameter.
    // Inferred logic in includes/crmperks-cf.php
    if (isset($_POST['vxcf_form_data'])) {
        $data = unserialize(base64_decode($_POST['vxcf_form_data']));
    }
    
  5. Requirement for is_admin(): Note that init (which includes crmperks-cf.php) is wrapped in an is_admin() check in setup_main. However, admin-ajax.php and REST API requests often satisfy is_admin() or the necessary context for these hooks to fire and the files to be included.

4. Nonce Acquisition Strategy

While Contact Form 7 submissions require a _wpcf7_nonce, the plugin itself does not appear to implement a separate nonce for its processing logic.

Obtaining the CF7 Nonce:

  1. Identify Form: Find a page containing a Contact Form 7 form.
  2. Create Test Page: If no form exists, create one:
    • wp post create --post_type=page --post_status=publish --post_title="Contact" --post_content='[contact-form-7 id="123" title="Contact form 1"]'
  3. Navigate & Extract:
    • Use browser_navigate to the page.
    • Use browser_eval to extract the nonce and form ID:
      () => {
          const form = document.querySelector('.wpcf7-form');
          return {
              nonce: form.querySelector('input[name="_wpcf7_nonce"]').value,
              id: form.querySelector('input[name="_wpcf7"]').value,
              unit_tag: form.querySelector('input[name="_wpcf7_unit_tag"]').value
          };
      }
      

5. Exploitation Strategy

The exploit involves sending a standard form submission request with an additional malicious parameter.

Step-by-Step Plan:

  1. Verify Sink: Search the plugin directory for the exact parameter name:
    • grep -r "unserialize(base64_decode" .
  2. Generate Payload: Since no POP chain is present in the plugin itself, use a core WordPress chain or a simple generic object to trigger a recognizable state (e.g., a class that exists in the environment).
    • Example Base64 Payload (for a stdClass): Tzo4OiJzdGRDbGFzcyI6MDp7fQ== (serialized stdClass)
  3. Construct HTTP Request:
    • URL: http://localhost:8080/wp-json/contact-form-7/v1/contact-forms/[ID]/feedback
    • Method: POST
    • Content-Type: application/x-www-form-urlencoded
    • Body:
      _wpcf7=[ID]&_wpcf7_version=X.X.X&_wpcf7_locale=en_US&_wpcf7_unit_tag=[TAG]&_wpcf7_container_post=0&_wpcf7_nonce=[NONCE]&your-name=test&your-email=test@example.com&your-subject=test&your-message=test&vxcf_form_data=Tzo4OiJzdGRDbGFzcyI6MDp7fQ==
      

6. Test Data Setup

  1. Install Plugins: Install contact-form-7 and cf7-zendesk version 1.1.4.
  2. Create Form: Create a default Contact Form 7.
  3. Create Page: Create a page named "Attack Surface" and embed the form shortcode.
  4. Zendesk Config: (Optional) The plugin might require a dummy Zendesk account to be "active" to reach the entry_created logic.
    • Check if self::$feeds_res or similar checks exist. If so, use wp option add to insert a dummy feed.

7. Expected Results

  • Success: The PHP process will attempt to unserialize the object. If a POP chain is used (e.g., one that writes a file), the file will appear in the filesystem.
  • Indicator: If using a logger or a specialized POP chain that triggers an error (like __wakeup on a non-existent class), the WordPress debug log (wp-content/debug.log) will show an "Attempt to unserialize non-existent class" error.

8. Verification Steps

  1. Check Logs: tail -f wp-content/debug.log to see if unserialize threw errors related to the payload.
  2. Monitor Filesystem: If the payload targets file creation: ls -la /var/www/html/wp-content/.
  3. Trace Method: Use wp eval to check if the specific integration file is loaded:
    • wp eval "var_dump(class_exists('vxcf_zendesk') && method_exists('vxcf_zendesk', 'entry_created'));"

9. Alternative Approaches

If the vxcf_form_data parameter is not the correct sink:

  1. Alternative Parameters: Check for vxcf_fields, crmperks_fields, or vxcf_form_fields.
  2. Different Hook: Attempt exploitation via WPForms or Elementor if Contact Form 7 is not yielding results. Each uses a different hook (e.g., wpforms_process_entry_save), but they all eventually route to the same vulnerable processing logic.
  3. Manual Sync: Look for AJAX actions in pro/plugin-api.php or includes/plugin-pages.php that might allow an admin (or someone with a valid nonce) to manually trigger the sync, which might also use unserialize().
Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Zendesk plugin for WordPress is vulnerable to unauthenticated PHP Object Injection due to the insecure use of deserialization functions on user-controlled input during form submissions. Attackers can exploit this by submitting malicious serialized PHP objects, potentially leading to remote code execution or file deletion if a suitable POP chain is present in the environment.

Vulnerable Code

// cf7-zendesk.php line 962 in version 1.1.4
     if(!is_array($value)){
          $value=maybe_unserialize($value);
     }

---

// Inferred logic in includes/crmperks-cf.php (referenced by the research plan)
if (isset($_POST['vxcf_form_data'])) {
    $data = unserialize(base64_decode($_POST['vxcf_form_data']));
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/cf7-zendesk/1.1.4/cf7-zendesk.php /home/deploy/wp-safety.org/data/plugin-versions/cf7-zendesk/1.1.5/cf7-zendesk.php
--- /home/deploy/wp-safety.org/data/plugin-versions/cf7-zendesk/1.1.4/cf7-zendesk.php	2025-02-21 18:36:26.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/cf7-zendesk/1.1.5/cf7-zendesk.php	2025-05-22 12:08:02.000000000 +0000
@@ -2,7 +2,7 @@
 /**
 * Plugin Name: Contact Form 7 Zendesk
 * Description: Integrates Contact Form 7, <a href="https://wordpress.org/plugins/contact-form-entries/">Contact Form Entries Plugin</a> and many other forms with Zendesk allowing form submissions to be automatically sent to your Zendesk account 
-* Version: 1.1.4
+* Version: 1.1.5
 * Requires at least: 3.8
 * Author URI: https://www.crmperks.com
 * Plugin URI: https://www.crmperks.com/plugins/contact-form-plugins/contact-form-zendesk-plugin/
@@ -24,7 +24,7 @@
   public  $crm_name = "zendesk";
   public  $id = "vxcf_zendesk";
   public  $domain = "vxcf-zendesk";
-  public  $version = "1.1.4";
+  public  $version = "1.1.5";
   public  $update_id = "6000015";
   public  $min_cf_version = "1.0";
   public $type = "vxcf_zendesk";
@@ -959,7 +959,7 @@
       $value=$value['value'];   
      }
      if(!is_array($value)){
-          $value=maybe_unserialize($value);
+         // $value=maybe_unserialize($value);
      }
   
   }

Exploit Outline

An unauthenticated attacker can exploit this vulnerability by targeting form submission endpoints for integrated plugins like Contact Form 7 or WPForms. The attacker submits a POST request to the form's feedback or submission handler (e.g., /wp-json/contact-form-7/v1/contact-forms/[ID]/feedback). The payload is a serialized PHP object, typically Base64-encoded and passed through a parameter such as 'vxcf_form_data' or standard form fields. The plugin's entry creation logic processes this input using maybe_unserialize() or unserialize(), triggering the object injection. While the attacker may need to obtain a form-specific nonce (like _wpcf7_nonce), the vulnerability itself does not require administrative authentication.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.