CVE-2025-49352

Order Cancellation & Returns for WooCommerce <= 1.1.12 - Authenticated (Subscriber+) Insecure Direct Object Reference

mediumAuthorization Bypass Through User-Controlled Key
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
1.1.13
Patched in
170d
Time to patch

Description

The Order Cancellation & Returns for WooCommerce plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 1.1.12 due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.1.12
PublishedDecember 31, 2025
Last updatedJune 18, 2026
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-49352 ## 1. Vulnerability Summary The **Order Cancellation & Returns for WooCommerce** plugin (<= 1.1.10) contains an Insecure Direct Object Reference (IDOR) vulnerability. The plugin fails to adequately verify if the current authenticated user has permission …

Show full research plan

Exploitation Research Plan: CVE-2025-49352

1. Vulnerability Summary

The Order Cancellation & Returns for WooCommerce plugin (<= 1.1.10) contains an Insecure Direct Object Reference (IDOR) vulnerability. The plugin fails to adequately verify if the current authenticated user has permission to access or perform actions on a specific order or return request. Specifically, a Subscriber-level user can provide a "key" (likely an order_id or return_id) to an AJAX endpoint to retrieve information or trigger processes related to orders belonging to other users.

The CVSS vector C:L/I:N/A:N suggests the primary impact is Information Disclosure (Confidentiality: Low), meaning an attacker can likely view sensitive order/return details of other customers but cannot necessarily modify them.

2. Attack Vector Analysis

  • Endpoint: WordPress AJAX endpoint /wp-admin/admin-ajax.php.
  • Action: Likely wp_ajax_wcor_get_order_details, wp_ajax_wcor_load_return_form, or wp_ajax_wcor_view_return_details (inferred).
  • Vulnerable Parameter: order_id or return_id (inferred).
  • Authentication: Subscriber-level credentials (or any logged-in user).
  • Preconditions: At least one order or return request must exist in the system belonging to a different user (the victim).

3. Code Flow (Inferred)

  1. Entry Point: An authenticated user sends a POST request to admin-ajax.php with a specific action (e.g., wcor_load_return_data).
  2. Nonce Verification: The plugin likely calls check_ajax_referer('wcor_nonce', 'security').
  3. Parameter Extraction: The code retrieves the ID: $order_id = $_POST['order_id'];.
  4. Data Fetching: The plugin calls wc_get_order($order_id) or queries the database for return data associated with that ID.
  5. Vulnerability (The Sink): The plugin proceeds to return HTML or JSON containing order details (items, prices, status, perhaps address) without verifying if $order->get_customer_id() === get_current_user_id().
  6. Response: The attacker receives the victim's order information.

4. Nonce Acquisition Strategy

The plugin likely localizes a nonce for its AJAX operations on the WooCommerce "My Account" page.

  1. Identify Shortcode: The plugin functionality is typically active on the WooCommerce Account page.
  2. Setup: Ensure WooCommerce is installed and the [woocommerce_my_account] shortcode is present on a page (usually /my-account/).
  3. Execution:
    • Login as the Attacker (Subscriber).
    • Use browser_navigate to go to http://localhost:8080/my-account/orders/.
    • Use browser_eval to extract the nonce and the AJAX action name.
  4. JS Variable Target:
    • Search the page source for wp_localize_script data.
    • Common patterns: window.wcor_ajax_obj?.nonce or window.wcor_params?.security.

5. Exploitation Strategy

Step 1: Discover the Endpoint

Since the source is not provided, first scan the plugin directory for AJAX registrations:

grep -r "wp_ajax_" /var/www/html/wp-content/plugins/wc-order-cancellation-return/

Look for actions that return data (e.g., "get", "load", "view").

Step 2: Information Disclosure Attack

Assuming the action is wcor_view_return_request and the nonce key is wcor_nonce:

Request:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=wcor_view_return_request&order_id=[VICTIM_ORDER_ID]&security=[NONCE]
    

Step 3: Targeted Payload (Example)

If the vulnerability is in a form loader:

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
Cookie: [ATTACKER_COOKIES]

action=wcor_load_cancel_order_form&order_id=123&security=a1b2c3d4e5

(Where 123 is the victim's order ID)

6. Test Data Setup

  1. Victim User: Create a user customer_victim (role: customer).
  2. Victim Order:
    • Use WP-CLI to create an order for the victim.
    • wp wc shop_order create --customer_id=[VICTIM_ID] --status=completed --user=admin
    • Add a line item to the order so there is data to leak.
  3. Attacker User: Create a user attacker_subscriber (role: subscriber).
  4. Note Order ID: Capture the ID of the created order (e.g., 123).

7. Expected Results

  • Success: The response (JSON or HTML) contains details of Order 123, such as the product name, order total, or customer notes, even though the attacker_subscriber did not place that order.
  • Failure: The response returns a 403 Forbidden, invalid nonce, or an error message stating "You do not have permission to view this order."

8. Verification Steps

  1. Check Output: Verify that the strings returned in the HTTP response match the data created for the victim's order.
    # Example check if the leaked order contained a specific product
    # Response Body: "...<td>Premium Quality Widget</td>..."
    
  2. Validate Ownership: Use WP-CLI to confirm the order actually belongs to the victim, proving the IDOR:
    wp post get [ORDER_ID] --field=post_author
    # Or via WC CLI
    wp wc shop_order get [ORDER_ID] --user=admin | grep customer_id
    

9. Alternative Approaches

  • Brute Force IDs: If the order IDs are sequential, attempt to iterate through IDs 1 to [LATEST_ID] to dump all return requests in the system.
  • Check Return Requests: If the IDOR is not on order_id, it may be on return_id. Look for custom post types registered by the plugin (e.g., wcor_return) and try to access those via the AJAX handler.
  • REST API: Check if the plugin registers any REST routes in includes/class-rest-api.php (inferred) which might lack permission_callback.
    grep -r "register_rest_route" /var/www/html/wp-content/plugins/wc-order-cancellation-return/
    
Research Findings
Static analysis — not yet PoC-verified

Summary

The Order Cancellation & Returns for WooCommerce plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) in versions up to 1.1.10. This vulnerability allows authenticated users with Subscriber-level permissions to access sensitive order and return information belonging to other customers by providing unauthorized order IDs to specific AJAX endpoints that lack ownership verification.

Vulnerable Code

// Inferred from AJAX registration and logic flow in wc-order-cancellation-return
// Likely located in includes/class-wcor-ajax.php

public function wcor_load_cancel_order_form() {
    check_ajax_referer('wcor_nonce', 'security');
    $order_id = $_POST['order_id'];
    $order = wc_get_order($order_id);

    // Vulnerability: The plugin proceeds to return data without verifying 
    // if $order->get_customer_id() === get_current_user_id()
    
    // ... code to generate and echo order details HTML/JSON ...
}

Security Fix

--- includes/class-wcor-ajax.php
+++ includes/class-wcor-ajax.php
@@ -10,6 +10,11 @@
     $order_id = $_POST['order_id'];
     $order = wc_get_order($order_id);
 
+    if ( ! $order || get_current_user_id() !== $order->get_customer_id() ) {
+        wp_send_json_error( array( 'message' => 'Permission denied' ) );
+        wp_die();
+    }
+
     // Logic to return order or return details follows...

Exploit Outline

1. Authenticate as a Subscriber-level user on the target WordPress site. 2. Navigate to the WooCommerce 'My Account' page to capture the security nonce (e.g., 'wcor_nonce') localized in the plugin's frontend scripts. 3. Identify a target Order ID belonging to a different user. 4. Send a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to 'wcor_load_cancel_order_form' or 'wcor_view_return_request', providing the 'security' nonce and the target 'order_id'. 5. The server will return the private details of the victim's order (items, status, prices) in the response because it fails to verify that the current user owns the requested object.

Check if your site is affected.

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