SupportCandy – Helpdesk & Customer Support Ticket System <= 3.4.4 - Authenticated (Subscriber+) Insecure Direct Object Reference
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:NTechnical Details
<=3.4.4Source Code
WordPress.org SVNThis 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:
- The attacker must know or guess the ID of a target attachment (usually a standard WordPress media/attachment post ID).
- The attacker must have at least one active ticket to which they can add a reply.
3. Code Flow (Inferred)
- Entry Point: The AJAX action
wp_ajax_wpsc_add_replytriggers the handler (likely insideclass-wpsc-tickets.phpor an AJAX controller). - Authorization Check: The plugin checks if the user is logged in and perhaps if they have access to the
ticket_idprovided in the request. - Processing Attachments: The code iterates through the IDs provided in the
description_attachmentsparameter. - Sink: The plugin performs a database update (likely changing the
post_parentof the attachment or updating a customwpscattachment mapping table) to link the attachment to the new reply/ticket. - 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.
- Shortcode Identification: SupportCandy typically uses the
[supportcandy]shortcode to render the customer portal. - Page Creation:
wp post create --post_type=page --post_title="Support" --post_status=publish --post_content='[supportcandy]' - Navigation: Navigate to the newly created page as a logged-in Subscriber.
- Nonce Extraction: SupportCandy usually localizes data into a global object.
- Target Variable:
window.wpsc_ajax_common?.nonceorwindow.wpsc_ticket_list?.nonce(inferred). - Command:
browser_eval("window.wpsc_ajax_common.nonce")
- Target Variable:
- 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_idof the Victim's file (viawp-clifor 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
- Plugin Installation: Install and activate
supportcandyversion 3.4.4. - Enable Attachments: Ensure ticket attachments are enabled in SupportCandy settings.
- Users:
- Create user
victim(Subscriber). - Create user
attacker(Subscriber).
- Create user
- Victim Ticket:
- Log in as
victim. - Create a ticket.
- Upload a file (ID
123).
- Log in as
- Attacker Ticket:
- Log in as
attacker. - Create a ticket (ID
456).
- Log in as
- Portal Page: Create a page with
[supportcandy]to facilitate nonce retrieval.
7. Expected Results
- The HTTP response for the
wpsc_add_replyaction 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:
Check Attachment Parent:
wp post get [VICTIM_ATTACHMENT_ID] --field=post_parentExpected: The
post_parentshould now be the ID of the Attacker's reply or ticket, not the Victim's.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_idcolumn 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_ticketaction for the samedescription_attachmentsparameter vulnerability. If an attacker can specify attachments during ticket creation, the logic may be identical.
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
@@ -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.