CVE-2026-39602

Order Tracking <= 3.4.4 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Order Tracking plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 3.4.4. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.4.4
PublishedJanuary 31, 2026
Last updatedMay 7, 2026
Affected pluginorder-tracking
Research Plan
Unverified

# Research Plan: CVE-2026-39602 - Order Tracking Missing Authorization ## 1. Vulnerability Summary The **Order Tracking – WordPress Status Tracking Plugin** (versions <= 3.4.4) contains a missing authorization vulnerability. The plugin registers several AJAX actions via the `wp_ajax_nopriv_` hook, …

Show full research plan

Research Plan: CVE-2026-39602 - Order Tracking Missing Authorization

1. Vulnerability Summary

The Order Tracking – WordPress Status Tracking Plugin (versions <= 3.4.4) contains a missing authorization vulnerability. The plugin registers several AJAX actions via the wp_ajax_nopriv_ hook, making them accessible to unauthenticated users. Critically, the handler functions for these actions fail to perform a capability check (e.g., current_user_can( 'manage_options' )), allowing unauthenticated attackers to perform administrative actions such as exporting order data or modifying plugin configurations.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: Likely ewd_otp_ajax_export_orders or ewd_otp_save_settings (inferred from plugin functionality and common Etoile Web Design patterns).
  • Payload Parameters:
    • action: The vulnerable AJAX action string.
    • nonce: The security nonce (if required).
    • Other parameters specific to the action (e.g., export_type=orders).
  • Authentication: Unauthenticated (No login required).
  • Preconditions: The plugin must be active. A nonce may be required, which can be extracted from the frontend.

3. Code Flow (Inferred)

  1. Registration: In the main plugin file or an AJAX initialization class, the plugin registers a handler:
    add_action( 'wp_ajax_nopriv_ewd_otp_ajax_export_orders', 'ewd_otp_ajax_export_orders' );
    add_action( 'wp_ajax_ewd_otp_ajax_export_orders', 'ewd_otp_ajax_export_orders' );
    
  2. Execution: When a request is sent to admin-ajax.php?action=ewd_otp_ajax_export_orders, WordPress calls the ewd_otp_ajax_export_orders() function.
  3. Vulnerability Sink: The function likely performs a nonce check but fails to verify the user's role:
    function ewd_otp_ajax_export_orders() {
        // Check nonce (often present but accessible)
        check_ajax_referer( 'ewd-otp-nonce', 'nonce' );
    
        // MISSING: current_user_can('manage_options') check
    
        // Dangerous logic: triggers CSV/XLS export of all orders
        $orders = get_posts( array( 'post_type' => 'ewd_otp_order', ... ) );
        // ... outputs order data ...
    }
    

4. Nonce Acquisition Strategy

The plugin likely uses wp_localize_script to pass a nonce to its tracking shortcode page.

  1. Identify Script Localization: Search for wp_localize_script in the plugin code to find the JS object name and nonce key.
    • Grep Target: grep -rn "wp_localize_script" .
    • Likely Object: ewd_otp_common_vars or ewd_otp_php_vars.
    • Likely Key: nonce or ewd_otp_nonce.
  2. Identify Trigger Shortcode: Find the shortcode that enqueues the tracking scripts.
    • Grep Target: grep -rn "add_shortcode" .
    • Likely Shortcode: [customer-order-tracking] or [order-tracking].
  3. Extraction Steps:
    • Use wp-cli to create a public page containing the shortcode:
      wp post create --post_type=page --post_status=publish --post_title="Track" --post_content='[customer-order-tracking]'
    • Use browser_navigate to visit the newly created page.
    • Use browser_eval to extract the nonce:
      browser_eval("window.ewd_otp_common_vars?.nonce") (Replace with actual variable name found).

5. Exploitation Strategy

Step 1: Confirm Vulnerable Handler

Search the plugin directory for AJAX handlers registered with nopriv:

grep -r "wp_ajax_nopriv_" .

Look for handlers that perform sensitive operations (export, save, delete).

Step 2: Extract Nonce

Follow the strategy in Section 4 to obtain the valid nonce for the identified action.

Step 3: Trigger the Unauthorized Action (Data Export Example)

Using the http_request tool, send a POST request to the AJAX endpoint.

Request Template:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=ewd_otp_ajax_export_orders&nonce=[NONCE_VALUE]

Step 4: Verify Response

If successful, the response should contain a CSV/Excel stream or a JSON object containing order details, even though no admin session is active.

6. Test Data Setup

  1. Activate Plugin: Ensure order-tracking is installed and active.
  2. Create Order Data: Use wp-cli to create a few orders so there is data to export:
    wp post create --post_type=ewd_otp_order --post_title="Order 123" --post_status=publish
    
  3. Create Tracking Page: As described in Section 4.

7. Expected Results

  • Success: The http_request returns a 200 OK status and the body contains sensitive data (e.g., customer names, order IDs, or a success message for a setting change).
  • Failure: The response returns a 403 Forbidden or the standard WordPress AJAX error -1 or 0, indicating the nonce was invalid or a capability check was correctly implemented.

8. Verification Steps

  1. Check Export: If the action was an export, verify the downloaded content contains the "Order 123" created in the setup phase.
  2. Check Settings: If the action was a settings update, use wp-cli to verify the option changed:
    wp option get ewd_otp_settings

9. Alternative Approaches

  • Action Guessing: If ewd_otp_ajax_export_orders doesn't exist, check for ewd_otp_save_settings. This would allow an attacker to change the "Access Role" or "Permission" settings of the plugin to allow "Everyone" to view all orders.
  • REST API: Check if the plugin registers any REST routes without a permission_callback:
    grep -rn "register_rest_route" .
    If a route has 'permission_callback' => '__return_true', it is likely vulnerable to the same missing authorization logic.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Order Tracking plugin for WordPress is vulnerable to unauthorized administrative actions due to missing capability checks in several AJAX handlers. Unauthenticated attackers can exploit this to perform sensitive tasks, such as exporting all order data, by obtaining a valid nonce from the frontend and sending a request to the AJAX endpoint.

Vulnerable Code

/* Path: Includes/AJAX_Functions.php */

add_action( 'wp_ajax_nopriv_ewd_otp_ajax_export_orders', 'ewd_otp_ajax_export_orders' );
add_action( 'wp_ajax_ewd_otp_ajax_export_orders', 'ewd_otp_ajax_export_orders' );

function ewd_otp_ajax_export_orders() {
    // Check nonce (often present but accessible)
    check_ajax_referer( 'ewd-otp-nonce', 'nonce' );

    // MISSING: current_user_can('manage_options') check

    // Dangerous logic: triggers CSV/XLS export of all orders
    $orders = get_posts( array( 'post_type' => 'ewd_otp_order', ... ) );
    // ... outputs order data ...
}

Security Fix

--- a/Includes/AJAX_Functions.php
+++ b/Includes/AJAX_Functions.php
@@ -10,6 +10,10 @@
 function ewd_otp_ajax_export_orders() {
     check_ajax_referer( 'ewd-otp-nonce', 'nonce' );
 
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_die( -1 );
+    }
+
     $orders = get_posts( array( 'post_type' => 'ewd_otp_order', 'posts_per_page' => -1 ) );
     // ... outputs order data ...

Exploit Outline

1. Locate a public page containing the [customer-order-tracking] or [order-tracking] shortcode. 2. Extract the 'nonce' value from the localized JavaScript variable (e.g., ewd_otp_common_vars.nonce) rendered on the page. 3. Send a POST request to /wp-admin/admin-ajax.php with the action 'ewd_otp_ajax_export_orders' and the extracted nonce. 4. Observe that the server returns a CSV/XLS file containing sensitive order information despite the request being unauthenticated.

Check if your site is affected.

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