WP Promoter <= 1.3 - Missing Authorization to Unauthenticated Statistics Reset via wpp-reset_stats AJAX Action
Description
The WP Promoter plugin for WordPress is vulnerable to unauthorized modification of data due to a missing capability check on the reset_stats() function in versions up to, and including, 1.3. The function is hooked to both the wp_ajax_wpp-reset_stats and wp_ajax_nopriv_wpp-reset_stats actions and contains no authentication, authorization, or nonce validation. This makes it possible for unauthenticated attackers to reset the plugin's bar and popup statistics by deleting the wpp_bar and wpp_popup options.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
# Exploitation Research Plan - CVE-2026-9014 (WP Promoter) ## 1. Vulnerability Summary The **WP Promoter** plugin (<= 1.3) contains a missing authorization vulnerability in its statistics reset functionality. The function `reset_stats()` is incorrectly exposed to unauthenticated users via the `wp_a…
Show full research plan
Exploitation Research Plan - CVE-2026-9014 (WP Promoter)
1. Vulnerability Summary
The WP Promoter plugin (<= 1.3) contains a missing authorization vulnerability in its statistics reset functionality. The function reset_stats() is incorrectly exposed to unauthenticated users via the wp_ajax_nopriv_wpp-reset_stats hook. Because the function lacks any capability checks (current_user_can) or CSRF protection (nonces), any unauthenticated attacker can trigger a reset of the plugin's bar and popup statistics by deleting the underlying WordPress options.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
wpp-reset_stats - HTTP Method:
POST(standard for AJAX, thoughGETmight also work depending on implementation) - Parameters:
action=wpp-reset_stats - Authentication: None required (vulnerable via
noprivhook) - Preconditions: The plugin must be active.
3. Code Flow
Based on the vulnerability description, the execution flow is as follows:
- Entry Point: An HTTP request hits
admin-ajax.phpwith the parameteraction=wpp-reset_stats. - Hook Execution: WordPress triggers the
wp_ajax_nopriv_wpp-reset_statshook (for logged-out users) orwp_ajax_wpp-reset_stats(for logged-in users). - Target Function: The plugin's
reset_stats()function (inferred) is called. - Missing Check: The function fails to call
check_ajax_referer()orcurrent_user_can('manage_options'). - The Sink: The function executes
delete_option('wpp_bar')anddelete_option('wpp_popup')(quoted from description). - Response: The plugin likely exits using
wp_die()orwp_send_json_success().
4. Nonce Acquisition Strategy
According to the vulnerability description, the reset_stats() function contains no nonce validation.
- Action String: Not applicable.
- Bypass: No bypass is necessary as the security check is entirely absent in the vulnerable versions.
Note: If testing reveals a nonce is actually present but the description was slightly inaccurate, the agent should search for wp_localize_script in the plugin source to identify the JS variable name (likely something like wpp_vars or wpp_ajax) and use browser_eval to extract it.
5. Exploitation Strategy
The goal is to demonstrate that an unauthenticated request can successfully delete the statistics options.
Step-by-step Plan:
- Prepare Request: Construct a POST request to the AJAX endpoint.
- Execute Request: Use
http_requestto send the payload. - Payload Structure:
- URL:
{{base_url}}/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=wpp-reset_stats
- URL:
6. Test Data Setup
To verify the impact, we must first ensure the statistics options exist and contain data.
- Initialize Options: Use WP-CLI to create the options that the plugin uses for statistics.
wp option update wpp_bar '{"views": 100, "clicks": 50}' --format=json wp option update wpp_popup '{"views": 200, "clicks": 75}' --format=json - Confirm Setup:
wp option get wpp_bar wp option get wpp_popup
7. Expected Results
- HTTP Response: The server should return a
200 OKstatus. The body might be empty,0,1, or a JSON success message depending on how the plugin terminates the AJAX call. - Database State: The options
wpp_barandwpp_popupshould no longer exist in thewp_optionstable (or should be reset to default/empty values).
8. Verification Steps
After the http_request tool completes, verify the deletion using WP-CLI:
- Check Options:
wp option get wpp_bar wp option get wpp_popup - Success Criteria: If WP-CLI returns an error like
Error: Could not get 'wpp_bar' option., the exploit is successful because the unauthenticated request triggered thedelete_option()call.
9. Alternative Approaches
- Method Variation: If
POSTfails, attempt aGETrequest:/wp-admin/admin-ajax.php?action=wpp-reset_stats. - Parameter Variation: If the options are not deleted, check the source code for a specific "type" parameter (e.g.,
action=wpp-reset_stats&type=bar) that might be required to target a specific option, though the description implies both are deleted. - Capability Check Verification: Attempt the request with a low-privileged user (Subscriber) to confirm that no capability checks are enforced for any level of user.
Summary
The WP Promoter plugin for WordPress (versions <= 1.3) allows unauthenticated attackers to reset plugin statistics due to missing authorization and CSRF checks in its AJAX handler. The `reset_stats` function is hooked to the `nopriv` AJAX action and fails to verify user permissions or nonces before deleting key configuration options.
Vulnerable Code
// File: wp-promoter.php (inferred from plugin slug) add_action( 'wp_ajax_wpp-reset_stats', 'reset_stats' ); add_action( 'wp_ajax_nopriv_wpp-reset_stats', 'reset_stats' ); function reset_stats() { delete_option('wpp_bar'); delete_option('wpp_popup'); wp_die(); }
Security Fix
@@ -1,6 +1,9 @@ add_action( 'wp_ajax_wpp-reset_stats', 'reset_stats' ); -add_action( 'wp_ajax_nopriv_wpp-reset_stats', 'reset_stats' ); function reset_stats() { + check_ajax_referer( 'wpp-reset-stats-nonce', 'nonce' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_die( -1 ); + } delete_option('wpp_bar'); delete_option('wpp_popup'); wp_die();
Exploit Outline
To exploit this vulnerability, an unauthenticated attacker can send a crafted POST request to the WordPress AJAX endpoint. 1. Target Endpoint: /wp-admin/admin-ajax.php 2. Authentication: None required. 3. Method: POST 4. Payload: A form-urlencoded body containing the parameter 'action=wpp-reset_stats'. 5. Mechanism: Because the plugin registers the 'wpp-reset_stats' action with 'wp_ajax_nopriv_', any logged-out visitor can trigger the handler. Since the handler lacks capability checks (current_user_can) and CSRF protection (check_ajax_referer), the server will execute delete_option() calls for the statistics data ('wpp_bar' and 'wpp_popup') upon receiving the request.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.