CVE-2025-14079

ELEX WordPress HelpDesk & Customer Ticketing System <= 3.3.5 - Missing Authorization to Authenticated (Subscriber+) Settings Update

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
3.3.6
Patched in
1d
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=3.3.5
PublishedFebruary 4, 2026
Last updatedFebruary 5, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

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 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_general action does not perform a current_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_general
    • nonce: A valid nonce (extracted from the UI).
    • [setting_name]: Various global settings defined by the plugin. Examples likely include support_email, ticket_prefix, or custom field configurations.
  • Preconditions: The plugin must be active. An attacker needs a valid Subscriber account.

3. Code Flow (Inferred)

  1. Registration: The plugin registers the AJAX hook:
    add_action( 'wp_ajax_eh_crm_ticket_general', array( $this, 'eh_crm_ticket_general' ) );
  2. Trigger: A Subscriber sends a POST request to admin-ajax.php with action=eh_crm_ticket_general.
  3. Verification (Weak): The function eh_crm_ticket_general calls check_ajax_referer() or wp_verify_nonce() using a shared action string (e.g., 'eh_crm_ticket_general' or a generic 'wsdesk_nonce').
  4. Authorization (Missing): The function proceeds to update options using update_option() or a similar mechanism without checking if the user is an administrator.
  5. 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.

  1. Identify the Localization Object: The plugin likely uses wp_localize_script to pass the nonce to JavaScript. In this plugin, the object is likely named wsdesk_ajax_object or eh_crm_ajax_object.
  2. Extraction Method:
    • Log in as a Subscriber.
    • Navigate to the WordPress Dashboard (/wp-admin/index.php).
    • Use browser_eval to extract the nonce.
  3. 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).

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:

  1. Create Attacker: Create a Subscriber user.
  2. Capture Nonce: Login as the Subscriber and extract the nonce using the browser.
  3. Identify Settings: Common setting fields in this plugin's general settings include eh_crm_support_email.
  4. 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
      
  5. Confirm Update: Check if the setting changed.

6. Test Data Setup

  1. Install Plugin: ELEX HelpDesk & Customer Ticketing System v3.3.5.
  2. Create User:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
  3. 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.php request returns a success response (likely JSON or a 1 / 0 string).
  • The global option eh_crm_support_email (or whichever field was targeted) is successfully changed in the database.

8. Verification Steps

  1. Via WP-CLI:
    wp option get eh_crm_support_email
    Confirm it matches attacker@evil.com.
  2. 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: Use grep -r "update_option" . inside the plugin directory to find which options are modified in the eh_crm_ticket_general function.
  • Examine POST processing: Check the function body of eh_crm_ticket_general (likely in admin/class-eh-crm-admin.php) to see exactly how it iterates over $_POST to save settings.
  • Check Shared Nonces: If the eh_crm_ticket_general nonce isn't found, try the nonce used for wsdesk_admin_ajax. ELEX plugins often reuse the same nonce for multiple AJAX actions.

Inferred Potential Settings to Target:

  • eh_crm_ticket_prefix
  • eh_crm_reply_email
  • wsdesk_email_api_key (if integrated)
Research Findings
Static analysis — not yet PoC-verified

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

--- a/admin/class-eh-crm-admin.php
+++ b/admin/class-eh-crm-admin.php
@@ -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.