CVE-2026-7106

Highland Software Custom Role Manager <= 1.0.0 - Authenticated (Subscriber+) Privilege Escalation

highImproper Privilege Management
8.8
CVSS Score
8.8
CVSS Score
high
Severity
1.0.1
Patched in
1d
Time to patch

Description

The Highland Software Custom Role Manager plugin for WordPress is vulnerable to Privilege Escalation in versions up to and including 1.0.0. This is due to insufficient authorization checks in the hscrm_save_user_roles() function, which is hooked to the personal_options_update action accessible by any authenticated user. This makes it possible for authenticated attackers, with Subscriber-level access or higher, to potentially modify user roles via the profile update form.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.0.0
PublishedApril 26, 2026
Last updatedApril 27, 2026

What Changed in the Fix

Changes introduced in v1.0.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: Privilege Escalation in Highland Software Custom Role Manager ## Vulnerability Summary The **Highland Software Custom Role Manager** plugin (<= 1.0.0) contains a privilege escalation vulnerability in `includes/user-ui.php`. The function `hscrm_save_user_roles()` is hooked to `perso…

Show full research plan

Research Plan: Privilege Escalation in Highland Software Custom Role Manager

Vulnerability Summary

The Highland Software Custom Role Manager plugin (<= 1.0.0) contains a privilege escalation vulnerability in includes/user-ui.php. The function hscrm_save_user_roles() is hooked to personal_options_update, which executes when any user updates their own profile.

The function performs an insufficient authorization check by verifying current_user_can('edit_user', $user_id). In WordPress, all users (including Subscribers) have the edit_user capability for their own User ID. Because the function fails to check for a more restrictive capability (like promote_users), it allows any authenticated user to supply an array of roles via the hscrm_roles[] parameter, which are then assigned to their account, enabling a Subscriber to promote themselves to Administrator.

Attack Vector Analysis

  • Endpoint: /wp-admin/profile.php
  • Hook: personal_options_update
  • Required Authentication: Subscriber or higher.
  • Vulnerable Parameter: hscrm_roles[]
  • Security Control Bypassed: Lack of promote_users or manage_options check in the save logic.

Code Flow

  1. Entry Point: User submits the profile update form at /wp-admin/profile.php.
  2. Hook Trigger: WordPress triggers personal_options_update (for self-updates) or edit_user_profile_update (for admin-updates).
  3. Function Call: hscrm_save_user_roles($user_id) is executed (includes/user-ui.php).
  4. Auth Check (Weak): if (!current_user_can('edit_user', $user_id)) passes because a Subscriber can edit their own profile.
  5. Nonce Check: wp_verify_nonce(...) validates $_POST['hscrm_roles_nonce'] against the action hscrm_save_user_roles.
  6. Input Processing: $_POST['hscrm_roles'] is sanitized using sanitize_key but is not validated against the current user's authority to assign those roles.
  7. Sink: The code (truncated in snippet, but inferred) updates the user's roles using $user->add_role() or $user->set_role() based on the provided list, which includes administrator.

Nonce Acquisition Strategy

The hscrm_roles_nonce is required for the exploit. This nonce is unique to the authenticated user and can be found in the HTML of the user's own profile page.

  1. Log in as a Subscriber user.
  2. Navigate to /wp-admin/profile.php.
  3. Locate the hidden input field:
    <input type="hidden" id="hscrm_roles_nonce" name="hscrm_roles_nonce" value="[NONCE_VALUE]">
  4. Also locate the standard WordPress profile nonce _wpnonce (action update-user_{ID}) required to successfully submit the profile form.

Exploitation Strategy

  1. Preparation: Use a Subscriber account.
  2. Information Gathering:
    • Fetch /wp-admin/profile.php and extract:
      • hscrm_roles_nonce
      • _wpnonce
      • The current user's user_id (usually found in the form action or a hidden input).
  3. Execution: Send a POST request to /wp-admin/profile.php.
    • Action: update
    • Parameters:
      • _wpnonce: extracted standard WP nonce.
      • hscrm_roles_nonce: extracted plugin nonce.
      • from: profile
      • checkuser_id: [your_user_id]
      • user_id: [your_user_id]
      • nickname: attacker (or any string)
      • email: attacker@example.com
      • hscrm_roles[]: administrator
  4. Verification: Check the response for a redirect back to profile.php?updated=1.

Test Data Setup

  1. Install Plugin: Ensure highland-software-custom-role-manager version 1.0.0 is active.
  2. Create Attacker User:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password
    
  3. Identify ID:
    wp user get attacker --field=ID
    

Expected Results

A successful exploit will result in the attacker user being assigned the administrator role. The plugin's logic for multiple roles may also store these in the hscrm_custom_roles user meta, but the immediate WordPress roles array should reflect the promotion.

Verification Steps

After the HTTP request, verify the promotion using WP-CLI:

# Check standard WordPress roles
wp user get attacker --field=roles

# Check plugin-specific custom meta
wp user meta get attacker hscrm_custom_roles

Alternative Approaches

If direct promotion to administrator is blocked by internal WP filters (unlikely in this context), try promoting to a custom role created by the plugin that has high privileges (if any exist).

  1. Check for custom roles: wp role list --fields=role,capabilities
  2. If an admin-equivalent custom role exists (e.g., custom_manager), use hscrm_roles[]=custom_manager instead.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Highland Software Custom Role Manager plugin (<= 1.0.0) is vulnerable to privilege escalation because the `hscrm_save_user_roles()` function uses a weak capability check. Authenticated users, such as Subscribers, can assign themselves the Administrator role by submitting a profile update request with the `hscrm_roles[]` parameter.

Vulnerable Code

// includes/user-ui.php @ line 220
add_action('personal_options_update', 'hscrm_save_user_roles');
add_action('edit_user_profile_update', 'hscrm_save_user_roles');
add_action('user_register', 'hscrm_save_user_roles');

function hscrm_save_user_roles($user_id) {

    /**
     * SECURITY: Capability check
     */
    if (!current_user_can('edit_user', $user_id)) {
        return;
    }

Security Fix

--- includes/user-ui.php
+++ includes/user-ui.php
@@ -224,7 +224,7 @@
     /**
      * SECURITY: Capability check
      */
-    if (!current_user_can('edit_user', $user_id)) {
+    if (!hscrm_user_can_manage_roles()) {
         return;
     }

Exploit Outline

An authenticated attacker with Subscriber-level permissions can escalate their privileges by performing the following steps: 1. Log in to the WordPress dashboard and navigate to the profile edit page (/wp-admin/profile.php). 2. Extract the 'hscrm_roles_nonce' value from the hidden input field in the page source and the standard WordPress '_wpnonce' used for profile updates. 3. Send a POST request to /wp-admin/profile.php with the action 'update', providing the standard nonces and setting the 'hscrm_roles[]' parameter to 'administrator'. 4. Because the plugin only verifies if the user has the 'edit_user' capability for the targeted ID (which WordPress defaults to true for a user's own profile), the function will process the request and grant the attacker the Administrator role.

Check if your site is affected.

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