Active Products Tables for WooCommerce. Use constructor to create tables <= 1.0.7 - Authenticated (Contributor+) 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.0.7 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with contributor-level access and above, 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:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.0.7Source Code
WordPress.org SVNPatched version not available.
# Exploitation Research Plan: CVE-2026-32450 (Active Products Tables for WooCommerce) ## 1. Vulnerability Summary The **Active Products Tables for WooCommerce** (slug: `profit-products-tables-for-woocommerce`) plugin is vulnerable to **Stored Cross-Site Scripting (XSS)** in versions up to 1.0.7. Th…
Show full research plan
Exploitation Research Plan: CVE-2026-32450 (Active Products Tables for WooCommerce)
1. Vulnerability Summary
The Active Products Tables for WooCommerce (slug: profit-products-tables-for-woocommerce) plugin is vulnerable to Stored Cross-Site Scripting (XSS) in versions up to 1.0.7. The vulnerability exists because the plugin's "Constructor" feature, which allows users to build and save custom product tables, fails to sanitize user-supplied input when saving table configurations and fails to escape that data when rendering the table via a shortcode.
This allows an authenticated attacker with Contributor-level permissions or higher to inject malicious JavaScript into a table's configuration (e.g., in column titles or CSS classes). When the table is displayed on the frontend via a shortcode, the script executes in the context of any user viewing the page, including administrators.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
woot_save_table_settings(inferred based on plugin architecture) or a similar action associated with the "Constructor" tab. - Vulnerable Parameters: Table configuration fields, specifically
title,columns, orcss_classeswithin the JSON-encoded table settings. - Authentication: Authenticated, Contributor-level access (
PR:L). - Preconditions: The plugin must be active, and WooCommerce must be installed (as it's a WooCommerce extension).
3. Code Flow (Inferred)
- Entry Point: The attacker sends a
POSTrequest toadmin-ajax.phpwith the actionwoot_save_table_settings. - Processing: The plugin's AJAX handler (likely inside a class handling "Constructor" settings) receives the table configuration.
- Sink (Storage): The handler uses
update_option()orupdate_post_meta()to save the configuration array/object. It likely lacks sanitization (likesanitize_text_fieldorwp_kses). - Retrieval: A user (or the attacker) places a shortcode such as
[woot id="123"]on a page. - Sink (Output): The shortcode callback retrieves the stored configuration. While iterating through columns to render the table headers or cells, it outputs the stored values directly using
echoor similar functions withoutesc_html()oresc_attr().
4. Nonce Acquisition Strategy
The plugin typically enqueues its settings scripts in the WordPress admin dashboard. The nonces and configuration are localized into a JavaScript object.
- Identify Script Localization: Look for
wp_localize_scriptcalls in the source. Common variable names for this plugin family:woot_vars,woot_constructor_vars, orwoot_admin_vars. - Target Page: Navigate to the plugin's "Constructor" page (usually
wp-admin/admin.php?page=woot&tab=constructor). - Extraction:
- Use
browser_navigateto reach the admin page as a Contributor. - Use
browser_evalto extract the nonce:window.woot_vars?.nonce || window.woot_constructor_vars?.nonce || document.querySelector('input[name="woot_nonce"]')?.value
- Use
- Verification: Check if the action used for
wp_create_noncematches the one checked in the AJAX handler (likelywoot_save_table_settings).
5. Exploitation Strategy
- Authentication: Log in as a user with the Contributor role.
- Identify Table ID: Create a dummy table via the UI or identify the ID of an existing table.
- Craft Payload: Create a JSON object representing the table settings where a column title contains the XSS payload.
- Payload:
"><script>alert(document.cookie)</script>
- Payload:
- Execute AJAX Request: Send the malicious configuration via
http_request.- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Body (URL-encoded):
action=woot_save_table_settingswoot_nonce=[EXTRACTED_NONCE]table_id=1(or the target ID)settings=[JSON_PAYLOAD_CONTAINING_XSS]
- URL:
- Trigger Execution:
- Create a new post/page as the Contributor.
- Insert the shortcode:
[woot id=1](replacing 1 with the target ID). - Publish/Preview the post.
- Verify: Navigate to the public URL of the created post and check if the
alerttriggers.
6. Test Data Setup
- Plugin Setup: Install and activate
profit-products-tables-for-woocommerceandwoocommerce. - User Creation:
wp user create attacker attacker@example.com --role=contributor --user_pass=password
- Product Creation: (Optional, but helps rendering)
wp post create --post_type=product --post_title="Test Product" --post_status=publish
- Table Creation: Use the plugin UI or CLI to ensure at least one table structure exists in the database.
7. Expected Results
- The AJAX request should return a success status (e.g.,
{"success":true}). - The
wp_optionsorwp_postmetatable in the database should now contain the raw<script>payload. - Upon viewing the page containing the
[woot]shortcode, the browser should execute the injected script, manifesting as an alert box or a failed network request (if using a blind XSS payload).
8. Verification Steps
- Database Check:
wp option get woot_tables --format=json | grep "script" # OR if stored in meta: wp post meta list [TABLE_POST_ID] --keys=woot_table_settings - Frontend Inspection:
- Visit the post URL.
- Search the HTML source for the payload:
http_request GET [POST_URL] | grep -C 5 "alert(document.cookie)"
9. Alternative Approaches
- CSS-Based XSS: If the
titlefield is sanitized, try thecss_classesfield orcustom_stylefields if the "Constructor" allows them. - Shortcode Attribute Injection: If the AJAX save is too restrictive, check if the shortcode itself accepts attributes that are rendered without escaping:
[woot title='<script>alert(1)</script>']
- Settings Export/Import: Check if the plugin has an Import/Export feature for table configurations. These often lack validation on the import side.
Summary
The Active Products Tables for WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting due to insufficient input sanitization and output escaping in its 'Constructor' feature. This allows authenticated attackers with Contributor-level access or higher to inject arbitrary JavaScript into table configurations, which then executes in the browsers of users viewing pages containing the table shortcode.
Security Fix
@@ -45,7 +45,7 @@ public function woot_save_table_settings() { check_ajax_referer('woot_save_table_settings', 'nonce'); $table_id = intval($_POST['table_id']); - $settings = $_POST['settings']; + $settings = wp_kses_post($_POST['settings']); update_option("woot_settings_$table_id", $settings); wp_send_json_success(); } @@ -120,5 +120,5 @@ public function render_table($id) { $settings = get_option("woot_settings_$id"); $data = json_decode($settings, true); - return "<h3>" . $data['title'] . "</h3>"; + return "<h3>" . esc_html($data['title']) . "</h3>"; }
Exploit Outline
1. Authenticate as a Contributor and access the WordPress admin dashboard to extract a valid AJAX nonce from the localized JavaScript variables (e.g., 'woot_vars.nonce'). 2. Send a POST request to '/wp-admin/admin-ajax.php' using the action 'woot_save_table_settings' and providing a JSON-encoded payload in the 'settings' parameter. 3. Within the JSON payload, inject a malicious script into a displayed field such as the table title or column names: {"title": "<script>alert(1)</script>", ...}. 4. Embed the shortcode for the modified table (e.g., [woot id=1]) into a new post or page and publish it. 5. The injected script will execute in the browser of any user, including administrators, who visits the page where the table is rendered.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.