Highland Software Custom Role Manager <= 1.0.0 - Authenticated (Subscriber+) Privilege Escalation
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:HTechnical Details
<=1.0.0What Changed in the Fix
Changes introduced in v1.0.1
Source Code
WordPress.org SVN# 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_usersormanage_optionscheck in the save logic.
Code Flow
- Entry Point: User submits the profile update form at
/wp-admin/profile.php. - Hook Trigger: WordPress triggers
personal_options_update(for self-updates) oredit_user_profile_update(for admin-updates). - Function Call:
hscrm_save_user_roles($user_id)is executed (includes/user-ui.php). - Auth Check (Weak):
if (!current_user_can('edit_user', $user_id))passes because a Subscriber can edit their own profile. - Nonce Check:
wp_verify_nonce(...)validates$_POST['hscrm_roles_nonce']against the actionhscrm_save_user_roles. - Input Processing:
$_POST['hscrm_roles']is sanitized usingsanitize_keybut is not validated against the current user's authority to assign those roles. - 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 includesadministrator.
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.
- Log in as a Subscriber user.
- Navigate to
/wp-admin/profile.php. - Locate the hidden input field:
<input type="hidden" id="hscrm_roles_nonce" name="hscrm_roles_nonce" value="[NONCE_VALUE]"> - Also locate the standard WordPress profile nonce
_wpnonce(actionupdate-user_{ID}) required to successfully submit the profile form.
Exploitation Strategy
- Preparation: Use a Subscriber account.
- Information Gathering:
- Fetch
/wp-admin/profile.phpand extract:hscrm_roles_nonce_wpnonce- The current user's
user_id(usually found in the form action or a hidden input).
- Fetch
- 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:profilecheckuser_id:[your_user_id]user_id:[your_user_id]nickname:attacker(or any string)email:attacker@example.comhscrm_roles[]:administrator
- Action:
- Verification: Check the response for a redirect back to
profile.php?updated=1.
Test Data Setup
- Install Plugin: Ensure
highland-software-custom-role-managerversion 1.0.0 is active. - Create Attacker User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password - 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).
- Check for custom roles:
wp role list --fields=role,capabilities - If an admin-equivalent custom role exists (e.g.,
custom_manager), usehscrm_roles[]=custom_managerinstead.
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
@@ -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.