CVE-2026-11395

CF7 to Webhook <= 5.0.0 - Unauthenticated Server-Side Request Forgery via CF7 Field Placeholder in Webhook URL Host

highServer-Side Request Forgery (SSRF)
7.2
CVSS Score
7.2
CVSS Score
high
Severity
5.0.1
Patched in
1d
Time to patch

Description

The CF7 to Webhook plugin for WordPress is vulnerable to Server-Side Request Forgery in all versions up to, and including, 5.0.0 via the pull_the_trigger. This makes it possible for unauthenticated attackers to make web requests to arbitrary locations originating from the web application and can be used to query and modify information from internal services. Exploitation requires that the admin-configured webhook URL contains a Contact Form 7 field placeholder in the host segment of the URL, and that the affected form is publicly accessible.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=5.0.0
PublishedJune 17, 2026
Last updatedJune 18, 2026
Affected plugincf7-to-zapier

What Changed in the Fix

Changes introduced in v5.0.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets a Server-Side Request Forgery (SSRF) vulnerability in the **CF7 to Webhook** plugin (version <= 5.0.0). The vulnerability arises because the plugin allows Contact Form 7 (CF7) field placeholders (e.g., `[field_name]`) within the admin-configured Webhook URL. If a placehold…

Show full research plan

This research plan targets a Server-Side Request Forgery (SSRF) vulnerability in the CF7 to Webhook plugin (version <= 5.0.0). The vulnerability arises because the plugin allows Contact Form 7 (CF7) field placeholders (e.g., [field_name]) within the admin-configured Webhook URL. If a placeholder is placed in the host segment of the URL, an unauthenticated user can control the destination of the resulting HTTP request by providing a malicious value for that field during form submission.


1. Vulnerability Summary

  • Vulnerability: Unauthenticated SSRF via Host Placeholder.
  • Affected Component: CFTZ_Module_Zapier::pull_the_trigger in modules/zapier/class-module-zapier.php.
  • Root Cause: The plugin performs string replacement on the Webhook URL using user-supplied form data. If the admin includes a placeholder in the URL's host (e.g., https://[dynamic-server]/api), the plugin will resolve this placeholder using the raw, unsanitized value from the submitted form, allowing an attacker to redirect the request to internal or arbitrary external IP addresses.
  • Sinks: wp_remote_request() and wp_remote_get() within pull_the_trigger.

2. Attack Vector Analysis

  • Endpoint: Contact Form 7 REST API submission endpoint: POST /wp-json/contact-form-7/v1/contact-forms/<id>/feedback.
  • Authentication: Unauthenticated (publicly accessible CF7 forms).
  • Payload Parameter: Any CF7 field name that has been configured as a placeholder in the Webhook URL.
  • Precondition: An administrator must have configured a Webhook URL containing a placeholder in the host portion (e.g., http://[target-host]/).

3. Code Flow

  1. Entry Point: An unauthenticated user submits a Contact Form 7 form.
  2. Trigger: CF7 fires a submission hook (likely wpcf7_mail_sent or similar).
  3. Module Interception: CFTZ_Module_CF7 (the CF7 integration module) gathers the form data and identifies the configured Webhook settings.
  4. Action Dispatch: The plugin calls do_action( 'ctz_trigger_webhook', ... ).
  5. Vulnerable Sink: CFTZ_Module_Zapier::pull_the_trigger (hooked to ctz_trigger_webhook in define_hooks()) receives the $hook_url and $data (form inputs).
  6. Placeholder Replacement: Either in the caller or via the ctz_hook_url filter (referenced on line 121 of modules/zapier/class-module-zapier.php), the [placeholder] in the URL is replaced with the attacker-controlled value from $data.
  7. Request Execution: wp_remote_request( $hook_url, $args ) is called on line 133 with the manipulated URL.

4. Nonce Acquisition Strategy

While Contact Form 7 often works without strict nonces for public submissions, it typically provides a REST API nonce for its feedback endpoint.

  1. Identify Form: Find a page containing a CF7 form or create one.
  2. Create Test Page:
    wp post create --post_type=page --post_status=publish --post_title="SSRF Test" --post_content='[contact-form-7 id="123"]'
    
  3. Navigate and Extract:
    • Use browser_navigate to visit the page.
    • Use browser_eval to extract the CF7 configuration, which usually includes the REST URL and nonce.
    • JS Key: window.wpcf7.apiSettings.nonce or find it within the form's data-unit-tag and _wpcf7_nonce hidden input.
    • Script Example: browser_eval("document.querySelector('input[name=\"_wpcf7_nonce\"]').value")

5. Exploitation Strategy

Step 1: Pre-Configuration (Simulated Admin Setup)

To exploit this, a form must be configured with a placeholder in the host. Since we are testing the PoC, we will use WP-CLI to simulate an admin configuring a vulnerable webhook.

  1. Create a CF7 form with a field named remote_host.
  2. Set the Webhook URL to http://[remote_host]/api.

Step 2: The Attack Request

Send a POST request to the CF7 feedback endpoint.

  • URL: http://<wp-host>/wp-json/contact-form-7/v1/contact-forms/<form-id>/feedback
  • Method: POST
  • Headers: Content-Type: multipart/form-data or application/x-www-form-urlencoded
  • Body:
    • _wpcf7: <form-id>
    • _wpcf7_unit_tag: wpcf7-f<id>-p<page-id>-o1 (usually required by CF7)
    • _wpcf7_nonce: <extracted-nonce>
    • remote_host: 127.0.0.1:22 (The SSRF payload targeting internal SSH)

Step 3: Expected Result

The WordPress server will attempt to make an HTTP request to http://127.0.0.1:22/api.

6. Test Data Setup

  1. Install Plugins: contact-form-7 and cf7-to-zapier.
  2. Create Form:
    wp eval '
    $contact_form = WPCF7_ContactForm::get_template();
    $contact_form->set_title( "SSRF Vulnerable Form" );
    $contact_form->set_properties( array(
        "form" => "[text* remote_host placeholder \"Host\"] [submit \"Send\"]"
    ) );
    $id = $contact_form->save();
    echo "FORM_ID:" . $id;
    '
    
  3. Configure Webhook: (Requires setting the meta/properties that cf7-to-zapier reads. Assuming meta key _ctz_zapier_url)
    wp post nominate meta set <FORM_ID> _ctz_zapier_webhook "http://[remote_host]/ssrf-test"
    wp post nominate meta set <FORM_ID> _ctz_zapier_enabled "1"
    

7. Expected Results

  • Success: The http_request response (or the server logs) should indicate that the WordPress server initiated a connection to the host specified in the remote_host field.
  • Internal Discovery: If targeting 127.0.0.1, the response might contain information from an internal service or a timeout/connection refused error from an internal port, rather than an external Zapier/Webhook service.

8. Verification Steps

  1. Monitor Outgoing Requests: Use a tool like RequestBin or a local listener on the Docker host.
  2. Check Plugin Logic: Confirm that wp_remote_request was reached by placing a debug log in modules/zapier/class-module-zapier.php before line 133:
    sed -i '132i \error_log("SSRF Target: " . $hook_url);' /var/www/html/wp-content/plugins/cf7-to-zapier/modules/zapier/class-module-zapier.php
    
  3. Check Logs: After submission, check wp-content/debug.log for the "SSRF Target" entry containing the injected host.

9. Alternative Approaches

If the REST API endpoint is strictly protected:

  • Form Submission: Use the standard admin-ajax.php?action=wpcf7_submit or the frontend form submission path (POST to the page URL where the form is embedded).
  • Placeholder Variation: Try placeholders in other segments of the URL if the host is partially restricted (e.g., https://legit-site.com@[attacker-host]/).
  • Gopher/Other Schemes: Test if wp_remote_request handles schemes like gopher:// or ftp:// for deeper internal exploitation.

Check if your site is affected.

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