CVE-2025-9207

TI WooCommerce Wishlist <= 2.10.0 - Unauthenticated HTML Injection

mediumImproper Input Validation
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.11.0
Patched in
1d
Time to patch

Description

The TI WooCommerce Wishlist plugin for WordPress is vulnerable to HTML Injection in all versions up to, and including, 2.10.0. This is due to the plugin accepting hidden fields and not limiting the values or data that can input and is later output. This makes it possible for unauthenticated attackers to inject arbitrary HTML into wishlist items.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.10.0
PublishedDecember 12, 2025
Last updatedDecember 13, 2025

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on exploiting **CVE-2025-9207**, an unauthenticated HTML injection vulnerability in the **TI WooCommerce Wishlist** plugin. --- ### 1. Vulnerability Summary The TI WooCommerce Wishlist plugin (up to version 2.10.0) fails to properly validate and sanitize input from hidde…

Show full research plan

This research plan focuses on exploiting CVE-2025-9207, an unauthenticated HTML injection vulnerability in the TI WooCommerce Wishlist plugin.


1. Vulnerability Summary

The TI WooCommerce Wishlist plugin (up to version 2.10.0) fails to properly validate and sanitize input from hidden form fields submitted when adding items to a wishlist. Specifically, the plugin accepts arbitrary hidden fields during the wishlist item creation process and stores these values. When the wishlist is later viewed, these values are rendered without sufficient escaping, allowing an unauthenticated attacker to inject arbitrary HTML (which may lead to XSS depending on the browser/context) into the wishlist items.

2. Attack Vector Analysis

  • Vulnerable Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: tinvwl_addto (registered for both authenticated and unauthenticated users).
  • Vulnerable Parameter: Arbitrary parameters passed via $_POST (likely hidden fields or metadata keys like formdata).
  • Authentication: None required (Unauthenticated).
  • Preconditions:
    • WooCommerce must be installed and active.
    • TI WooCommerce Wishlist must be active.
    • At least one public product must exist to trigger the "Add to Wishlist" flow.

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers wp_ajax_tinvwl_addto and wp_ajax_nopriv_tinvwl_addto.
  2. Handler: The request is handled by a method (likely TINVWL_Public_Wishlist_Ajax::addto() in includes/public/wishlist/ajax.class.php).
  3. Data Processing: The handler processes the $_POST data. It likely iterates through submitted data to handle product variations or custom attributes.
  4. Storage: The unsanitized hidden field values are saved into the wishlist items table ({prefix}tinvwl_items) or as item meta.
  5. Sink: When a user views the wishlist (using the [ti_wishlistsview] shortcode), the plugin retrieves the items and outputs the stored field values directly to the HTML response without calling esc_html() or wp_kses().

4. Nonce Acquisition Strategy

The plugin uses a nonce for the tinvwl_addto action. This nonce is typically localized into the page where the "Add to Wishlist" button appears.

  1. Shortcode Identification: The plugin uses the shortcode [ti_wishlistsview] for the wishlist page and automatically adds "Add to Wishlist" buttons to WooCommerce product pages.
  2. Page Creation: Use WP-CLI to ensure a product exists.
    wp post create --post_type=product --post_title="Target Product" --post_status=publish
    
  3. Browser Navigation: Navigate to the product page.
  4. Extraction: The plugin localizes its settings in a JavaScript object, often named tinvwl_add_to_wishlist or tinv_wishlist.
    • Target Variable: window.tinvwl_add_to_wishlist (inferred from plugin history).
    • Nonce Key: nonce.
    • Command: browser_eval("window.tinvwl_add_to_wishlist?.nonce")

5. Exploitation Strategy

The goal is to inject HTML into a wishlist item via the AJAX "add" action.

Step 1: Test Data Setup

  • Ensure WooCommerce and TI WooCommerce Wishlist are active.
  • Create a product and note its ID.

Step 2: Nonce Retrieval

  • Navigate to the product page.
  • Extract the nonce using browser_eval.

Step 3: Exploit Request
Send a POST request to admin-ajax.php. Based on the vulnerability description "accepting hidden fields", we will attempt to pass extra parameters that the plugin might save as metadata.

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Parameters:
    • action: tinvwl_addto
    • tinvwl-product_id: [PRODUCT_ID]
    • tinvwl-p_id: [PRODUCT_ID]
    • tinvwl-product_variation: 0
    • tinvwl-product_type: simple
    • nonce: [EXTRACTED_NONCE]
    • tinvwl-hidden-field: <img src=x onerror=alert('CVE-2025-9207')> (The vulnerability specifically mentions hidden fields; this parameter name is a primary candidate for testing).

Step 4: Verification

  • Navigate to the Wishlist page (usually /wishlist/ or wherever the [ti_wishlistsview] shortcode is placed).
  • Check if the HTML is rendered and the script executes.

6. Test Data Setup

  1. Initialize WooCommerce:
    wp plugin install woocommerce --activate
    wp plugin install ti-woocommerce-wishlist --version=2.10.0 --activate
    
  2. Create Product:
    PRODUCT_ID=$(wp post create --post_type=product --post_title="Vulnerable Product" --post_status=publish --porcelain)
    
  3. Locate Wishlist Page:
    Find the page containing [ti_wishlistsview]. If none exists, create one:
    wp post create --post_type=page --post_title="My Wishlist" --post_content='[ti_wishlistsview]' --post_status=publish
    

7. Expected Results

  • The AJAX response should return {"status":true,...}.
  • Upon visiting the Wishlist page, the injected HTML (<h1>Hacked</h1> or a script tag) should be present in the DOM within the wishlist table or item details.

8. Verification Steps

  1. Check Database:
    Verify if the malicious string was saved to the custom table:
    wp db query "SELECT * FROM wp_tinvwl_items WHERE product_id = $PRODUCT_ID"
    
  2. Inspect Response:
    Use http_request to fetch the wishlist page and grep for the payload:
    # Use the tool to fetch the page and check for:
    # <img src=x onerror=alert('CVE-2025-9207')>
    

9. Alternative Approaches

If tinvwl-hidden-field is not the correct parameter:

  1. Variation Mapping: Try injecting into parameters that might be mapped to WooCommerce attributes, such as attribute_pa_[name].
  2. Formdata Parameter: Some versions of this plugin wrap submitted data in a formdata parameter. Try:
    • action=tinvwl_addto&nonce=[NONCE]&formdata=tinvwl-hidden%3D%3Ch1%3EInjected%3C%2Fh1%3E
  3. Wishlist Creation: Try injecting the HTML into the wishlist_name if the plugin allows unauthenticated wishlist creation (often handled via the same AJAX action if a wishlist_id is not provided).
Research Findings
Static analysis — not yet PoC-verified

Summary

The TI WooCommerce Wishlist plugin for WordPress (<= 2.10.0) is vulnerable to unauthenticated HTML injection because it fails to sanitize data submitted via arbitrary hidden form fields during the wishlist item addition process. Attackers can inject malicious HTML into wishlist items, which is then rendered unsafely when the wishlist is viewed by a user.

Vulnerable Code

// File: includes/public/wishlist/ajax.class.php

// Inferred logic in TINVWL_Public_Wishlist_Ajax::addto()
foreach ( $_POST as $key => $value ) {
    if ( strpos( $key, 'tinvwl-' ) === 0 ) {
        // Vulnerable: Arbitrary input accepted and stored without sanitization
        $form_data[$key] = $value;
    }
}

Security Fix

--- a/includes/public/wishlist/ajax.class.php
+++ b/includes/public/wishlist/ajax.class.php
@@ -120,7 +120,7 @@
 	foreach ( $_POST as $key => $value ) {
 		if ( strpos( $key, 'tinvwl-' ) === 0 ) {
-			$form_data[ $key ] = $value;
+			$form_data[ $key ] = sanitize_text_field( $value );
 		}
 	}

Exploit Outline

1. Access a public product page to retrieve a valid 'tinvwl_add_to_wishlist' nonce and product ID from the localized JavaScript variables. 2. Submit a POST request to 'wp-admin/admin-ajax.php' with the action 'tinvwl_addto', providing the nonce, product ID, and a malicious HTML payload (e.g., <img src=x onerror=alert(1)>) in an arbitrary parameter starting with 'tinvwl-' (such as 'tinvwl-hidden-field'). 3. The payload is stored in the wishlist items table and will execute when the wishlist page (containing the [ti_wishlistsview] shortcode) is visited by any user.

Check if your site is affected.

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