CVE-2025-12641

Awesome Support – WordPress HelpDesk & Support Plugin <= 6.3.6 - Missing Authorization to Unauthenticated Role Demotion

mediumMissing Authorization
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
6.3.7
Patched in
1d
Time to patch

Description

The Awesome Support - WordPress HelpDesk & Support Plugin for WordPress is vulnerable to authorization bypass due to missing capability checks in all versions up to, and including, 6.3.6. This is due to the 'wpas_do_mr_activate_user' function not verifying that a user has permission to modify other users' roles, combined with a nonce reuse vulnerability where public registration nonces are valid for privileged actions because all actions share the same nonce namespace. This makes it possible for unauthenticated attackers to demote administrators to low-privilege roles via the 'wpas-do=mr_activate_user' action with a user-controlled 'user_id' parameter, granted they can access the publicly available registration/submit ticket page to extract a valid nonce.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
Low
Availability

Technical Details

Affected versions<=6.3.6
PublishedJanuary 15, 2026
Last updatedJanuary 16, 2026
Affected pluginawesome-support

Source Code

WordPress.org SVN
Research Plan
Unverified

## Vulnerability Summary The **Awesome Support** plugin (versions <= 6.3.6) contains a critical authorization bypass in the `wpas_do_mr_activate_user` function. This function is intended to allow administrators or authorized personnel to manually activate users who have registered via the support po…

Show full research plan

Vulnerability Summary

The Awesome Support plugin (versions <= 6.3.6) contains a critical authorization bypass in the wpas_do_mr_activate_user function. This function is intended to allow administrators or authorized personnel to manually activate users who have registered via the support portal.

However, the function fails to implement any capability checks (e.g., current_user_can( 'manage_options' )), relying solely on a nonce for security. Due to a nonce reuse vulnerability, the nonce generated for unauthenticated users on the public registration or ticket submission pages is part of the same "namespace" (action string) as the one used for the privileged mr_activate_user action. Consequently, an unauthenticated attacker can obtain a valid nonce from the frontend and use it to trigger the user activation logic against an existing Administrator account, which forces the account's role to be demoted to the plugin's default "Client" role.

Attack Vector Analysis

  • Endpoint: The vulnerability is triggered via a GET request to the WordPress frontend (any page) with specific query parameters.
  • Vulnerable Action: wpas-do=mr_activate_user
  • Parameters:
    • wpas-do: Set to mr_activate_user.
    • user_id: The ID of the user to demote (typically 1 for the primary administrator).
    • _wpnonce: A valid WordPress nonce obtained from the frontend.
  • Authentication: None required (Unauthenticated).
  • Preconditions:
    • The plugin must be active.
    • A public-facing page containing an Awesome Support shortcode (like [ticket_submit] or [ticket_registration]) must be accessible to extract the nonce.

Code Flow

  1. Entry Point: The plugin registers a handler (likely hooked to init or template_redirect) that monitors the wpas-do query parameter.
  2. Dispatcher: In includes/functions-user.php (or similar), a function like wpas_do_actions() checks if isset( $_GET['wpas-do'] ).
  3. Vulnerable Function Call: If wpas-do equals mr_activate_user, it calls wpas_do_mr_activate_user().
  4. Missing Check: Inside wpas_do_mr_activate_user():
    • It retrieves $user_id = $_GET['user_id'].
    • It verifies the nonce: wp_verify_nonce( $_GET['_wpnonce'], 'wpas_nonce' ) (or a similar generic action string).
    • Crucially, it skips any current_user_can() check.
  5. Sink: It calls wpas_activate_user( $user_id ).
  6. Role Demotion: wpas_activate_user() fetches the user object and calls $user->set_role( 'client' ). If the target $user_id is an administrator, their role is immediately changed to client, stripping them of administrative access.

Nonce Acquisition Strategy

The plugin exposes the necessary nonce via wp_localize_script on any page where its support functionality is loaded.

  1. Identify Shortcode: The plugin uses [ticket_submit] for ticket submission.
  2. Create Trigger Page: Create a public page containing this shortcode to ensure the scripts and nonces are enqueued.
  3. Locate JS Object: The plugin typically localizes data into a JavaScript object named wpas_ajax_vars or wpas_ajax.
  4. Extract Nonce: Use browser_eval to extract the nonce:
    • Variable: wpas_ajax_vars.nonce or wpas_nonce.
    • Script Handle: wpas_scripts.

Exploitation Strategy

1. Test Data Setup

  • Ensure an administrator user exists (default ID 1).
  • Create a public page to expose the nonce.
wp post create --post_type=page --post_title="Support" --post_status=publish --post_content='[ticket_submit]'

2. Nonce Extraction

  1. Navigate to the /support page using browser_navigate.
  2. Execute browser_eval to find the nonce:
// Likely one of these based on plugin version
window.wpas_ajax_vars?.nonce || window.wpas_ajax?.nonce

3. Exploitation Request

Perform an unauthenticated GET request using the http_request tool.

  • URL: http://localhost:8888/
  • Method: GET
  • Query Parameters:
    • wpas-do: mr_activate_user
    • user_id: 1 (The Admin ID)
    • _wpnonce: [EXTRACTED_NONCE]

Example Construction:
GET /?wpas-do=mr_activate_user&user_id=1&_wpnonce=a1b2c3d4e5

4. Expected Response

The server will likely respond with a redirect (302) or a simple "User Activated" message, but the HTTP status code is less important than the side effect in the database.

Expected Results

  • The Administrator user (ID 1) will have their role changed from administrator to client.
  • The Administrator will no longer be able to access /wp-admin/.

Verification Steps

After sending the exploit request, verify the role change using WP-CLI:

# Check the role of the user with ID 1
wp user get 1 --field=roles

Success Criteria: The command returns client (or the default AS role) instead of administrator.

Alternative Approaches

If wpas-do=mr_activate_user is not accepted via GET, attempt the request as a POST to admin-ajax.php or the homepage, as some WordPress action dispatchers check $_REQUEST.

If the user_id parameter is not honored directly, check if the plugin expects user or id. Based on the vulnerability report, user_id is the confirmed parameter name.

If [ticket_submit] doesn't work, try these alternative shortcodes to trigger script loading:

  • [ticket_registration]
  • [my_tickets]
  • [ticket_list]
Research Findings
Static analysis — not yet PoC-verified

Summary

The Awesome Support plugin fails to perform authorization checks in the 'wpas_do_mr_activate_user' function, which is responsible for activating users. Because the plugin uses a generic nonce that is exposed to unauthenticated users on public registration pages, an attacker can reuse this nonce to trigger the activation logic against an administrator, causing their account to be demoted to a low-privilege 'client' role.

Vulnerable Code

// Inferred from research plan: likely in includes/functions-user.php
function wpas_do_mr_activate_user() {
    // Nonce check is present, but uses a generic action string shared with public actions
    if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'wpas_nonce' ) ) {
        return;
    }

    // Missing: current_user_can( 'manage_options' ) check

    $user_id = isset( $_GET['user_id'] ) ? intval( $_GET['user_id'] ) : 0;

    if ( $user_id ) {
        wpas_activate_user( $user_id );
    }
}

---

function wpas_activate_user( $user_id ) {
    $user = get_userdata( $user_id );
    if ( $user ) {
        // This call demotes any targeted user to the default 'client' role
        $user->set_role( 'client' );
        update_user_meta( $user_id, 'wpas_is_active', 1 );
    }
}

Security Fix

--- a/includes/functions-user.php
+++ b/includes/functions-user.php
@@ -10,6 +10,11 @@
-    if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'wpas_nonce' ) ) {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_die( __( 'You do not have permission to perform this action.', 'awesome-support' ) );
+    }
+
+    if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'], 'wpas_activate_user_' . $_GET['user_id'] ) ) {
         return;
     }

Exploit Outline

1. Identify a public-facing page on the target site containing an Awesome Support shortcode, such as [ticket_submit] or [ticket_registration]. 2. View the page source or use a browser console to extract the security nonce from the 'wpas_ajax_vars' or 'wpas_ajax' JavaScript object (usually variable 'nonce'). 3. Determine the User ID of the administrator to be demoted (commonly ID 1 for the primary admin). 4. Construct a GET request to the WordPress frontend using the following parameters: - 'wpas-do': mr_activate_user - 'user_id': [Target Admin ID] - '_wpnonce': [Extracted Nonce] 5. Send the request unauthenticated. The plugin will process the action and call 'set_role' on the target user, effectively stripping them of administrator privileges and assigning them the 'client' role.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.