WP Zendesk for Contact Form 7, WPForms, Elementor, Formidable and Ninja Forms <= 1.1.4 - Unauthenticated PHP Object Injection
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:HTechnical Details
What Changed in the Fix
Changes introduced in v1.1.5
Source Code
WordPress.org SVNThis 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]/feedbackorPOST /wp-admin/admin-ajax.php(if using the legacy AJAX handler).
- For Contact Form 7:
- Vulnerable Parameter:
vxcf_form_data(inferred from similar CRM Perks vulnerabilities). - Authentication: Unauthenticated.
- Preconditions:
- The plugin must be active.
- At least one form (e.g., Contact Form 7) must be created and accessible on the frontend.
- The plugin must be "hooked" into the form (default behavior).
3. Code Flow
- Entry Point: A user submits a form. For Contact Form 7, this triggers the
wpcf7_before_send_mailhook. - Plugin Callback:
vxcf_zendesk::setup_mainregisterscreate_entry_cfas a callback for that hook. - Method Execution:
create_entry_cfcalls$this->entry_created($lead, '0', $form_arr). - Vulnerable Sink: Inside
entry_created(located inincludes/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'])); } - Requirement for
is_admin(): Note thatinit(which includescrmperks-cf.php) is wrapped in anis_admin()check insetup_main. However,admin-ajax.phpand REST API requests often satisfyis_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:
- Identify Form: Find a page containing a Contact Form 7 form.
- 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"]'
- Navigate & Extract:
- Use
browser_navigateto the page. - Use
browser_evalto 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 }; }
- Use
5. Exploitation Strategy
The exploit involves sending a standard form submission request with an additional malicious parameter.
Step-by-Step Plan:
- Verify Sink: Search the plugin directory for the exact parameter name:
grep -r "unserialize(base64_decode" .
- 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==(serializedstdClass)
- Example Base64 Payload (for a
- 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==
- URL:
6. Test Data Setup
- Install Plugins: Install
contact-form-7andcf7-zendeskversion 1.1.4. - Create Form: Create a default Contact Form 7.
- Create Page: Create a page named "Attack Surface" and embed the form shortcode.
- Zendesk Config: (Optional) The plugin might require a dummy Zendesk account to be "active" to reach the
entry_createdlogic.- Check if
self::$feeds_resor similar checks exist. If so, usewp option addto insert a dummy feed.
- Check if
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
__wakeupon 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
- Check Logs:
tail -f wp-content/debug.logto see ifunserializethrew errors related to the payload. - Monitor Filesystem: If the payload targets file creation:
ls -la /var/www/html/wp-content/. - Trace Method: Use
wp evalto 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:
- Alternative Parameters: Check for
vxcf_fields,crmperks_fields, orvxcf_form_fields. - 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. - Manual Sync: Look for AJAX actions in
pro/plugin-api.phporincludes/plugin-pages.phpthat might allow an admin (or someone with a valid nonce) to manually trigger the sync, which might also useunserialize().
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
@@ -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.