CVE-2026-1251

SupportCandy – Helpdesk & Customer Support Ticket System <= 3.4.4 - Authenticated (Subscriber+) Insecure Direct Object Reference

mediumAuthorization Bypass Through User-Controlled Key
5.4
CVSS Score
5.4
CVSS Score
medium
Severity
3.4.5
Patched in
8d
Time to patch

Description

The SupportCandy – Helpdesk & Customer Support Ticket System plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 3.4.4 via the 'add_reply' function due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with subscriber-level access and above, to steal file attachments uploaded by other users by specifying arbitrary attachment IDs in the 'description_attachments' parameter, re-associating those files to their own tickets and removing access from the original owners.

CVSS Vector Breakdown

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

Technical Details

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

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps to exploit a confirmed Insecure Direct Object Reference (IDOR) vulnerability in the SupportCandy WordPress plugin. ## 1. Vulnerability Summary The SupportCandy plugin (<= 3.4.4) is vulnerable to an IDOR in the `add_reply` function. This occurs because the funct…

Show full research plan

This research plan outlines the steps to exploit a confirmed Insecure Direct Object Reference (IDOR) vulnerability in the SupportCandy WordPress plugin.

1. Vulnerability Summary

The SupportCandy plugin (<= 3.4.4) is vulnerable to an IDOR in the add_reply function. This occurs because the function accepts an array of attachment IDs via the description_attachments parameter without verifying that the current user has ownership or authorization over those specific attachments. An attacker can provide IDs of files uploaded by other users, causing the plugin to re-assign those files to the attacker’s ticket, thereby stealing access and potentially removing access from the original owner.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wpsc_add_reply (inferred from plugin naming conventions and function name)
  • Vulnerable Parameter: description_attachments (can be an array or comma-separated string of attachment IDs)
  • Authentication: Authenticated (Subscriber or higher). The attacker must have permission to create or reply to tickets (default behavior for SupportCandy users).
  • Preconditions:
    1. The attacker must know or guess the ID of a target attachment (usually a standard WordPress media/attachment post ID).
    2. The attacker must have at least one active ticket to which they can add a reply.

3. Code Flow (Inferred)

  1. Entry Point: The AJAX action wp_ajax_wpsc_add_reply triggers the handler (likely inside class-wpsc-tickets.php or an AJAX controller).
  2. Authorization Check: The plugin checks if the user is logged in and perhaps if they have access to the ticket_id provided in the request.
  3. Processing Attachments: The code iterates through the IDs provided in the description_attachments parameter.
  4. Sink: The plugin performs a database update (likely changing the post_parent of the attachment or updating a custom wpsc attachment mapping table) to link the attachment to the new reply/ticket.
  5. Vulnerability: There is no check (e.g., if (get_post_field('post_author', $attachment_id) == get_current_user_id())) before performing the re-association.

4. Nonce Acquisition Strategy

SupportCandy heavily relies on localized JavaScript objects to store nonces and AJAX URLs.

  1. Shortcode Identification: SupportCandy typically uses the [supportcandy] shortcode to render the customer portal.
  2. Page Creation:
    wp post create --post_type=page --post_title="Support" --post_status=publish --post_content='[supportcandy]'
    
  3. Navigation: Navigate to the newly created page as a logged-in Subscriber.
  4. Nonce Extraction: SupportCandy usually localizes data into a global object.
    • Target Variable: window.wpsc_ajax_common?.nonce or window.wpsc_ticket_list?.nonce (inferred).
    • Command: browser_eval("window.wpsc_ajax_common.nonce")
  5. Alternative: If the nonce is per-ticket, navigate to a specific ticket the attacker owns and look for localized data related to that ticket.

5. Exploitation Strategy

Step 1: Preliminary Data Gathering

  • Create a Victim (Subscriber) and an Attacker (Subscriber).
  • Victim creates a ticket and uploads a file (e.g., secret.txt).
  • Attacker creates a ticket.
  • Note the attachment_id of the Victim's file (via wp-cli for the PoC).

Step 2: The Attack Request

The attacker sends an AJAX request to re-associate the Victim's attachment with the Attacker's ticket.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Payload:
    action=wpsc_add_reply&
    ticket_id=[ATTACKER_TICKET_ID]&
    description=Stealing+your+files&
    description_attachments[]=[VICTIM_ATTACHMENT_ID]&
    wpsc_nonce=[EXTRACTED_NONCE]
    

Step 3: Result Analysis

If successful, the plugin response will indicate a successful reply addition. The Victim's attachment will now be linked to the Attacker's ticket.

6. Test Data Setup

  1. Plugin Installation: Install and activate supportcandy version 3.4.4.
  2. Enable Attachments: Ensure ticket attachments are enabled in SupportCandy settings.
  3. Users:
    • Create user victim (Subscriber).
    • Create user attacker (Subscriber).
  4. Victim Ticket:
    • Log in as victim.
    • Create a ticket.
    • Upload a file (ID 123).
  5. Attacker Ticket:
    • Log in as attacker.
    • Create a ticket (ID 456).
  6. Portal Page: Create a page with [supportcandy] to facilitate nonce retrieval.

7. Expected Results

  • The HTTP response for the wpsc_add_reply action returns a success code (JSON {"success": true}).
  • The attachment previously owned/viewable by the Victim is now listed as an attachment on the Attacker's ticket.
  • The Victim may no longer see the attachment on their own ticket, or it may appear as "broken" if the relationship is exclusive.

8. Verification Steps

After the exploit, use wp-cli to verify the IDOR:

  1. Check Attachment Parent:

    wp post get [VICTIM_ATTACHMENT_ID] --field=post_parent
    

    Expected: The post_parent should now be the ID of the Attacker's reply or ticket, not the Victim's.

  2. Check Meta/Custom Tables:
    If SupportCandy uses a custom table (e.g., wp_wpsc_attachments), query it:

    wp db query "SELECT * FROM wp_wpsc_attachments WHERE attachment_id = [VICTIM_ATTACHMENT_ID]"
    

    Expected: The ticket_id column should reflect the Attacker's ticket ID.

9. Alternative Approaches

  • Bulk Stealing: Provide a list of attachment IDs in the description_attachments[] array to steal multiple files at once.
  • Unauthorized Deletion: Check if re-associating an attachment "removes" it from the original ticket, effectively performing an unauthorized deletion/move.
  • Different Entry Points: Check the wpsc_create_ticket action for the same description_attachments parameter vulnerability. If an attacker can specify attachments during ticket creation, the logic may be identical.
Research Findings
Static analysis — not yet PoC-verified

Summary

The SupportCandy plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) via the 'add_reply' function. Authenticated attackers with subscriber-level access can supply arbitrary attachment IDs in the 'description_attachments' parameter to re-associate files uploaded by other users to their own tickets, thereby gaining unauthorized access to sensitive documents.

Vulnerable Code

// Inferred from plugin logic in class-wpsc-tickets.php
public function wpsc_add_reply() {
    // ... (logic to verify ticket ownership of the ticket being replied to) ...

    if ( isset( $_POST['description_attachments'] ) && ! empty( $_POST['description_attachments'] ) ) {
        $attachments = (array) $_POST['description_attachments'];
        foreach ( $attachments as $attachment_id ) {
            // VULNERABILITY: No check to ensure the current user owns this attachment_id
            // before re-parenting it to the new reply.
            wp_update_post( array(
                'ID'          => intval( $attachment_id ),
                'post_parent' => $reply_id,
            ) );
        }
    }
}

Security Fix

--- a/includes/class-wpsc-tickets.php
+++ b/includes/class-wpsc-tickets.php
@@ -102,6 +102,12 @@
 
     if ( isset( $_POST['description_attachments'] ) && ! empty( $_POST['description_attachments'] ) ) {
         $attachments = (array) $_POST['description_attachments'];
+        $current_user_id = get_current_user_id();
         foreach ( $attachments as $attachment_id ) {
+            $attachment = get_post( $attachment_id );
+            if ( ! $attachment || intval( $attachment->post_author ) !== $current_user_id ) {
+                continue;
+            }
             wp_update_post( array(
                 'ID'          => intval( $attachment_id ),
                 'post_parent' => $reply_id,

Exploit Outline

1. The attacker logs into the WordPress site as a Subscriber or any role with ticket access. 2. The attacker identifies a target attachment ID belonging to another user (e.g., via enumeration or predictive IDs). 3. The attacker navigates to the SupportCandy portal to extract a valid AJAX nonce, typically found in the localized 'wpsc_ajax_common' JavaScript object. 4. The attacker crafts a POST request to /wp-admin/admin-ajax.php with the action 'wpsc_add_reply'. 5. The payload includes a 'ticket_id' belonging to the attacker and the victim's attachment ID inside the 'description_attachments[]' array. 6. The server processes the request and re-assigns the victim's attachment to the attacker's ticket, allowing the attacker to view or download the file from their own ticket interface.

Check if your site is affected.

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