Combo Offers WooCommerce <= 4.2 - Authenticated (Contributor+) Stored Cross-Site Scripting
Description
The Combo Offers WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 4.2 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
<=4.2This research plan outlines the steps to investigate and exploit **CVE-2025-69088**, a Stored Cross-Site Scripting (XSS) vulnerability in the **Combo Offers WooCommerce** plugin. --- ### 1. Vulnerability Summary The **Combo Offers WooCommerce** plugin (versions <= 4.2) fails to properly sanitize a…
Show full research plan
This research plan outlines the steps to investigate and exploit CVE-2025-69088, a Stored Cross-Site Scripting (XSS) vulnerability in the Combo Offers WooCommerce plugin.
1. Vulnerability Summary
The Combo Offers WooCommerce plugin (versions <= 4.2) fails to properly sanitize and escape user-supplied data stored in "Combo Offer" configurations. Users with Contributor level permissions or higher can inject malicious scripts into fields related to offer creation. These scripts are subsequently executed in the browser of any user (including administrators) who views the affected offer on the frontend or within the WordPress admin dashboard.
2. Attack Vector Analysis
- Target Endpoint:
wp-admin/admin-ajax.php(for settings/meta updates) orwp-admin/post.php(if using a Custom Post Type). - Vulnerable Action: Likely a custom AJAX action registered for saving combo metadata, e.g.,
wp_ajax_save_combo_metaor similar (inferred). - Payload Parameter: Field parameters such as
combo_title,offer_text,button_label, or custom meta-box inputs (inferred). - Authentication Level: Contributor or higher.
- Preconditions: The plugin must be active and WooCommerce must be installed. The attacker must have credentials for a Contributor account.
3. Discovery & Code Flow
Because source files were not provided, the following discovery steps are required to ground the exploit in real identifiers:
- Identify Entry Points:
# Find AJAX actions available to authenticated users grep -rn "wp_ajax_" wp-content/plugins/woo-combo-offers/ # Find where metadata is updated (potential sinks) grep -rn "update_post_meta" wp-content/plugins/woo-combo-offers/ - Trace Input to Sink:
- Identify the function handling the AJAX request (e.g.,
save_combo_data). - Confirm if it uses
$_POSTdata directly inupdate_post_meta()withoutsanitize_text_field()orwp_kses().
- Identify the function handling the AJAX request (e.g.,
- Identify Output Sinks:
- Search for where the stored meta is retrieved and echoed:
grep -rn "get_post_meta" wp-content/plugins/woo-combo-offers/ | grep "echo"- Common locations include shortcode rendering functions or WooCommerce product display hooks (e.g.,
woocommerce_before_add_to_cart_form).
4. Nonce Acquisition Strategy
The plugin likely uses wp_localize_script to pass a security nonce to its administrative or editor scripts.
Identify Script Localization:
Search forwp_localize_scriptin the plugin code:grep -rn "wp_localize_script" wp-content/plugins/woo-combo-offers/Look for the object name and key (e.g.,
woo_combo_params.nonce).Extraction Steps:
- Step A: Create a Contributor user.
- Step B: Navigate to the "Combo Offers" or "Products" section in the dashboard.
- Step C: Use
browser_evalto extract the nonce:
// Example based on common naming conventions (verify with grep) window.woo_combo_admin_params?.nonce || window.woo_combo_obj?.ajax_nonce
5. Exploitation Strategy
Step 1: Data Injection
Using the http_request tool, send a POST request to admin-ajax.php to save a malicious payload.
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method: POST
- Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=[DISCOVERED_ACTION]& nonce=[EXTRACTED_NONCE]& post_id=[TARGET_PRODUCT_ID]& combo_title=Test Offer<script>alert(document.domain)</script>& [OTHER_REQUIRED_PARAMS]=value
Step 2: Triggering Execution
- Frontend: Navigate to the WooCommerce product page associated with
post_id. - Backend: Navigate to the "All Combo Offers" list or the specific Product Edit page in the admin dashboard.
6. Test Data Setup
- Environment: Ensure WooCommerce is active.
- Content: Create at least one WooCommerce product to attach the combo offer to.
- User: Create a user with the
contributorrole. - Plugin Config: If the plugin requires a specific "Combo" to be active, create a valid one first via the UI or WP-CLI.
7. Expected Results
- Injection Response: The AJAX request should return a
200 OKor a JSON success message (e.g.,{"success":true}). - Execution: When any user visits the product page, a JavaScript alert box showing the document domain should appear, confirming the script executed.
8. Verification Steps
After performing the exploit via HTTP, verify the data storage using WP-CLI:
# Check if the payload is stored in post_meta (replace meta_key with discovered key)
wp post meta list [POST_ID] --keys=[DISCOVERED_META_KEY]
9. Alternative Approaches
If the Contributor role cannot access the primary AJAX handler:
- Check Shortcodes: Look for shortcodes that allow saving data or state (rare for contributors, but possible in some "Offer" plugins).
- Check Post Edits: If the plugin adds a meta-box to the standard Post/Product editor, use the
editpostaction inpost.php. Contributors can often edit their own posts/products (if the plugin allows product creation for contributors). - Check Settings API: Look for
register_settingcalls that might lack proper capability checks, allowing a Contributor to modify global plugin options.
Summary
The Combo Offers WooCommerce plugin for WordPress (versions <= 4.2) is vulnerable to Stored Cross-Site Scripting (XSS) due to insufficient input sanitization and output escaping of combo offer metadata. Authenticated attackers with Contributor-level access or higher can inject arbitrary web scripts into configuration fields that execute when the content is rendered for other users, including administrators.
Exploit Outline
To exploit this vulnerability, an attacker with Contributor-level access or higher must first obtain a valid security nonce, typically found in the localized scripts of the WordPress admin dashboard. The attacker then crafts a POST request to 'admin-ajax.php' (using the plugin's metadata-saving action) or 'post.php'. The payload involves injecting a script, such as '<script>alert(document.domain)</script>', into vulnerable metadata parameters like 'combo_title' or 'offer_text'. Once the request is processed, the script is stored in the database and will execute whenever an administrator or site visitor views the affected product page or the combo offer configuration in the backend.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.