MC4WP: Mailchimp for WordPress <= 4.11.1 - Missing Authorization to Unauthenticated Arbitrary Subscription Deletion
Description
The MC4WP: Mailchimp for WordPress plugin for WordPress is vulnerable to Missing Authorization in all versions up to, and including, 4.11.1. This is due to the plugin trusting the `_mc4wp_action` POST parameter without validation, allowing unauthenticated attackers to force the form to process unsubscribe actions instead of subscribe actions. This makes it possible for unauthenticated attackers to arbitrarily unsubscribe any email address from the connected Mailchimp audience via the `_mc4wp_action` parameter, granted they can obtain the form ID (which is publicly exposed in the HTML source).
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:LTechnical Details
<=4.11.1What Changed in the Fix
Changes introduced in v4.12.0
Source Code
WordPress.org SVNThis research plan focuses on the Missing Authorization vulnerability in the **MC4WP: Mailchimp for WordPress** plugin, which allows unauthenticated attackers to unsubscribe any email address from a Mailchimp audience by manipulating the `_mc4wp_action` parameter in a form submission. --- ### 1. V…
Show full research plan
This research plan focuses on the Missing Authorization vulnerability in the MC4WP: Mailchimp for WordPress plugin, which allows unauthenticated attackers to unsubscribe any email address from a Mailchimp audience by manipulating the _mc4wp_action parameter in a form submission.
1. Vulnerability Summary
The vulnerability exists in the front-end form processing logic of the plugin. When a user submits a sign-up form, the plugin determines the action to take (e.g., subscribe, unsubscribe) based on the _mc4wp_action POST parameter. In affected versions (<= 4.11.1), the plugin fails to verify if the user is authorized to perform an unsubscribe action. Since the plugin is designed to allow unauthenticated sign-ups, it processes these requests globally. An attacker can craft a request that overrides the intended subscribe action with unsubscribe, effectively removing any known email address from the connected Mailchimp audience.
2. Attack Vector Analysis
- Endpoint: Any public-facing page where a Mailchimp for WordPress form is embedded.
- Method:
POST - Vulnerable Parameter:
_mc4wp_action - Required Authentication: None (Unauthenticated).
- Preconditions:
- The attacker must know the
_mc4wp_form_id(publicly visible in the HTML source). - The plugin must be connected to a valid Mailchimp API key.
- The victim's email address must already be subscribed to the audience associated with the form.
- The attacker must know the
3. Code Flow (Inferred from Source & Behavior)
- Entry Point:
MC4WP_Form_Listener(referenced inautoload.php) is loaded and hooks intotemplate_redirect,init, orwp_loadedto listen for form submissions. - Request Detection: The listener checks for the presence of the
_mc4wp_form_idPOST parameter. - Action Determination: The listener looks for
_mc4wp_action.- If absent, it defaults to
subscribe. - If present, it adopts the value provided in the request without checking permissions.
- If absent, it defaults to
- Logic Branching: The code passes the action to
MC4WP_Form::execute($action, $data)or a similar processing method. - Sink: The plugin uses the
MC4WP_API_V3class (referenced inautoload.php) to communicate with the Mailchimp API. If the action isunsubscribe, it sends a request to Mailchimp to update the member's status tounsubscribed.
4. Nonce Acquisition Strategy
Mailchimp for WordPress forms are designed for high conversion and, by default, do not require a WordPress nonce for standard sign-ups. This is confirmed by config/default-form-content.php, which contains only the email field and the submit button.
However, the plugin employs some anti-spam measures:
- Honeypot: A hidden field (often named
_mc4wp_honeypot) that must be empty. - Timestamp: A hidden field
_mc4wp_timestampcontaining a Unix timestamp.
Strategy:
- Navigate to a page containing the form.
- Extract the
_mc4wp_form_idfrom the hidden input. - Extract any anti-spam tokens (if present) from the HTML.
- No JavaScript-localized nonce is required for this specific exploit.
5. Exploitation Strategy
The goal is to force an unsubscribe action on an existing subscriber.
Step-by-Step Plan:
- Identify Form: Locate a page with an MC4WP form.
- Extract Parameters: Using
browser_navigateandbrowser_eval, extract thevalueof the hidden input_mc4wp_form_id. - Craft Payload:
_mc4wp_form_id: [Extracted ID]_mc4wp_action:unsubscribeEMAIL: [Target Email Address]_mc4wp_timestamp: [Current Unix Timestamp] (optional, but recommended)
- Execute Request: Use the
http_requesttool to send a POST request to the page URL.
Payload (URL-Encoded):
POST /target-page/ HTTP/1.1
Host: target.local
Content-Type: application/x-www-form-urlencoded
_mc4wp_form_id=123&_mc4wp_action=unsubscribe&EMAIL=victim@example.com&_mc4wp_timestamp=1738848000
6. Test Data Setup
- API Connection: Connect the plugin to a Mailchimp account (or a mock API).
- Create Form: Create a sign-up form via the plugin admin.
- Placement: Add the form to a post/page using the
[mc4wp_form]shortcode. - Add Subscriber: Manually add
victim@example.comto the Mailchimp audience (ensure status issubscribed). - Enable Logging: In plugin settings, ensure "Logging" is enabled to verify the action.
7. Expected Results
- Response: The page should reload and likely display a success message associated with unsubscription (e.g., "You have been unsubscribed").
- Mailchimp State: The email
victim@example.comshould have its status changed fromsubscribedtounsubscribedin the Mailchimp Audience dashboard. - Plugin Logs: The plugin's internal logs should show an
unsubscribeevent for the specified email.
8. Verification Steps
- Database Check: Check the
wp_poststable wherepost_type = 'mc4wp-form'to confirm the form ID existence. - Plugin Debug Log: Use
wp-clito read the MC4WP debug log (if defined in the settings or filesystem).cat wp-content/uploads/mc4wp-debug.log(path may vary).
- Mailchimp Verification: If possible, use
MC4WP_API_V3directly viawp evalto check the member status:wp eval '$api = new MC4WP_API_V3("YOUR_API_KEY"); print_r($api->get_subscriber("AUDIENCE_ID", "victim@example.com"));'
9. Alternative Approaches
- Gutenberg Block: If the standard shortcode is not used, target the form generated by the
mailchimp-for-wp/formGutenberg block. - AJAX Submission: Some configurations use AJAX. If the form has the
mc4wp-ajaxclass, the request should be sent toadmin-ajax.phpwithaction=mc4wp_submit_form.- Payload:
action=mc4wp_submit_form&_mc4wp_form_id=[ID]&_mc4wp_action=unsubscribe&EMAIL=[EMAIL]
- Payload:
- Different Actions: Test if other actions like
deleteare supported by the_mc4wp_actionparameter, althoughunsubscribeis the most common for front-end listeners.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.