WholeSale Products Dynamic Pricing Management WooCommerce <= 1.2 - Authenticated (Administrator+) Stored Cross-Site Scripting via Plugin Settings
Description
The WholeSale Products Dynamic Pricing Management WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in all versions up to, and including, 1.2 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with administrator-level permissions and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.2This research plan focuses on **CVE-2026-4479**, a Stored Cross-Site Scripting (XSS) vulnerability in the "WholeSale Products Dynamic Pricing Management WooCommerce" plugin. --- ### 1. Vulnerability Summary The **WholeSale Products Dynamic Pricing Management WooCommerce** plugin (versions <= 1.2)…
Show full research plan
This research plan focuses on CVE-2026-4479, a Stored Cross-Site Scripting (XSS) vulnerability in the "WholeSale Products Dynamic Pricing Management WooCommerce" plugin.
1. Vulnerability Summary
The WholeSale Products Dynamic Pricing Management WooCommerce plugin (versions <= 1.2) fails to sanitize and escape input saved within its administrative settings. Specifically, settings related to wholesale pricing labels or display messages are stored in the WordPress options table and subsequently rendered on both the administrative dashboard and potentially the frontend product pages without passing through security filters like esc_html(), esc_attr(), or wp_kses().
This allows an authenticated user with Administrator privileges to inject arbitrary JavaScript. While Administrators usually have the unfiltered_html capability, this vulnerability is critical in WordPress Multisite environments (where only Super Admins have unfiltered_html) or in hardened environments where this capability is explicitly disabled.
2. Attack Vector Analysis
- Endpoint: The plugin settings page, typically located at
/wp-admin/admin.php?page=wholesale-products-pricing-management(inferred slug). - Vulnerable Parameters: Administrative fields such as "Wholesale Price Label", "Text for Non-Wholesale Users", or "Pricing Table Header".
- Authentication: Administrator-level account is required.
- Precondition: The site must be a Multisite installation OR have
define( 'DISALLOW_UNFILTERED_HTML', true );inwp-config.php.
3. Code Flow (Inferred)
- Entry Point: The Administrator navigates to the plugin settings page.
- Processing (Store): A
POSTrequest is sent tooptions.php(if using the Settings API) or a custom handler hooked toadmin_init. - Data Sink (Database): The plugin calls
update_option()orupdate_post_meta()without usingsanitize_text_field()orwp_kses()on the input. - Retrieval (Source): When the settings page or a product page is loaded, the plugin calls
get_option(). - Output (Sink): The retrieved value is echoed directly into the HTML:
// Vulnerable Pattern $label = get_option('wholesale_price_label'); echo '<span class="label">' . $label . '</span>'; // XSS Sink
4. Nonce Acquisition Strategy
The plugin likely uses the standard WordPress Settings API or a custom form with wp_nonce_field.
- Identify the Page: Navigate to the plugin settings page:
/wp-admin/admin.php?page=wholesale-products-dynamic-pricing-management-woocommerce(Slug needs verification viawp plugin list). - Navigate and Extract:
- Use
browser_navigateto reach the settings page. - The Settings API uses a nonce field usually named
_wpnonce. - Action String: If it's a standard settings page, the action is often the option group name.
- Use
- Extraction Command:
// To be used with browser_eval document.querySelector('input[name="_wpnonce"]')?.value || document.querySelector('#_wpnonce')?.value;
5. Exploitation Strategy
The goal is to inject a stored XSS payload into a setting field and verify its execution.
Step 1: Locate the Settings Form
Access the admin page and identify the input fields. Common WooCommerce wholesale plugin options include wholesale_label or wholesale_price_text.
Step 2: Submit the Payload
Submit a POST request to the settings handler.
- URL:
http://localhost:8080/wp-admin/options.php(Standard for Settings API) - Content-Type:
application/x-www-form-urlencoded - Body:
option_page=wholesale_pricing_settings_group& action=update& _wpnonce=[EXTRACTED_NONCE]& wholesale_price_label=Wholesale<script>alert(document.domain)</script>& submit=Save+Changes
Step 3: Trigger the XSS
Navigate to either:
- The plugin settings page itself (Admin XSS).
- A product page on the frontend where the wholesale price is displayed (Frontend XSS).
6. Test Data Setup
- Plugin Installation: Ensure
wholesale-products-dynamic-pricing-management-woocommercev1.2 is installed and active. - Hardening: Add
define( 'DISALLOW_UNFILTERED_HTML', true );towp-config.phpto ensure even the Administrator is subject to sanitization checks (which the plugin fails to implement). - WooCommerce Setup: Ensure at least one product exists so the wholesale label can be rendered on the frontend.
7. Expected Results
- Storage: The database should contain the raw
<script>tag in thewp_optionstable. - Execution: When viewing the page, the browser should execute the script, appearing as a JavaScript alert or a failed resource load (if using a more complex payload).
- HTTP Response: The
POSTrequest should return a302redirect back to the settings page withsettings-updated=true.
8. Verification Steps
After the http_request, use wp-cli to confirm the injection:
# Check if the option value contains the payload
wp option get wholesale_price_label --allow-root
# Check if the output on the frontend is escaped
# (Should return the raw tag if vulnerable)
curl -s http://localhost:8080/product/test-product/ | grep "<script>alert"
9. Alternative Approaches
If the plugin does not use options.php but a custom AJAX handler:
- Grep for AJAX:
grep -r "wp_ajax_"in the plugin directory. - Target Action: Look for actions like
save_wholesale_settings. - New Strategy:
- Obtain nonce from a JS variable (e.g.,
window.wholesale_admin?.nonce). - Send
POSTtoadmin-ajax.phpwithaction=save_wholesale_settingsand the payload.
- Obtain nonce from a JS variable (e.g.,
If the XSS is only in the Admin area:
- Focus on the
admin_noticeshook or the form'svalueattribute:wholesale_price_label="><script>alert(1)</script>(Attribute breakout).
Summary
The WholeSale Products Dynamic Pricing Management WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting via administrative settings in versions up to 1.2. This vulnerability allows authenticated administrators to inject arbitrary JavaScript into settings like wholesale labels, which then executes when viewed on both the admin dashboard and frontend product pages.
Vulnerable Code
// Inferred vulnerability in settings rendering (e.g., admin/settings-display.php) $wholesale_label = get_option('wholesale_price_label'); echo '<input type="text" name="wholesale_price_label" value="' . $wholesale_label . '">'; // Vulnerable input value echo --- // Inferred vulnerability in frontend display (e.g., public/product-display.php) $label = get_option('wholesale_price_label'); echo '<span class="wholesale-label">' . $label . '</span>'; // Vulnerable output sink
Security Fix
@@ -10,1 +10,1 @@ -echo '<input type="text" name="wholesale_price_label" value="' . $wholesale_label . '">'; +echo '<input type="text" name="wholesale_price_label" value="' . esc_attr($wholesale_label) . '">'; @@ -25,1 +25,1 @@ -echo '<span class="wholesale-label">' . $label . '</span>'; +echo '<span class="wholesale-label">' . esc_html($label) . '</span>';
Exploit Outline
1. Login to the WordPress administrative dashboard as a user with Administrator privileges. 2. Navigate to the plugin settings page (typically via a 'Wholesale Pricing' menu entry). 3. Locate a text input field such as 'Wholesale Price Label' or 'Price Text'. 4. Inject a malicious payload into the field, such as: "><script>alert(document.domain)</script>. 5. Save the settings to commit the payload to the WordPress database (wp_options table). 6. Trigger the XSS by navigating back to the settings page or by viewing any product page on the frontend where the wholesale pricing label is displayed.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.