Order Cancellation & Returns for WooCommerce <= 1.1.12 - Authenticated (Subscriber+) Insecure Direct Object Reference
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:NTechnical Details
<=1.1.12# 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, orwp_ajax_wcor_view_return_details(inferred). - Vulnerable Parameter:
order_idorreturn_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)
- Entry Point: An authenticated user sends a POST request to
admin-ajax.phpwith a specificaction(e.g.,wcor_load_return_data). - Nonce Verification: The plugin likely calls
check_ajax_referer('wcor_nonce', 'security'). - Parameter Extraction: The code retrieves the ID:
$order_id = $_POST['order_id'];. - Data Fetching: The plugin calls
wc_get_order($order_id)or queries the database for return data associated with that ID. - 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(). - 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.
- Identify Shortcode: The plugin functionality is typically active on the WooCommerce Account page.
- Setup: Ensure WooCommerce is installed and the
[woocommerce_my_account]shortcode is present on a page (usually/my-account/). - Execution:
- Login as the Attacker (Subscriber).
- Use
browser_navigateto go tohttp://localhost:8080/my-account/orders/. - Use
browser_evalto extract the nonce and the AJAX action name.
- JS Variable Target:
- Search the page source for
wp_localize_scriptdata. - Common patterns:
window.wcor_ajax_obj?.nonceorwindow.wcor_params?.security.
- Search the page source for
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
- Victim User: Create a user
customer_victim(role: customer). - 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.
- Attacker User: Create a user
attacker_subscriber(role: subscriber). - 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 theattacker_subscriberdid 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
- 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>..." - 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
1to[LATEST_ID]to dump all return requests in the system. - Check Return Requests: If the IDOR is not on
order_id, it may be onreturn_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 lackpermission_callback.grep -r "register_rest_route" /var/www/html/wp-content/plugins/wc-order-cancellation-return/
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
@@ -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.