MoreConvert Wishlist for WooCommerce <= 1.9.19 - Unauthenticated Stored Cross-Site Scripting
Description
The MoreConvert Wishlist for WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.9.19 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers 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:N/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=1.9.19What Changed in the Fix
Changes introduced in v1.9.20
Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2026-57356 ## 1. Vulnerability Summary The **MoreConvert Wishlist for WooCommerce** plugin (versions <= 1.9.19) contains an unauthenticated stored cross-site scripting vulnerability. The issue exists in the handling of wishlist item additions, specifically where u…
Show full research plan
Exploitation Research Plan - CVE-2026-57356
1. Vulnerability Summary
The MoreConvert Wishlist for WooCommerce plugin (versions <= 1.9.19) contains an unauthenticated stored cross-site scripting vulnerability. The issue exists in the handling of wishlist item additions, specifically where user-supplied variation attributes or metadata are stored without sufficient sanitization. When these items are subsequently rendered in the wishlist table (on the frontend) or within the admin dashboard (e.g., analytics or wishlist management views), the injected scripts execute in the context of the viewing user.
2. Attack Vector Analysis
- Endpoint:
wp-admin/admin-ajax.php(or any frontend page via thewp_loadedhook). - AJAX Action:
wlfmc_add_to_wishlist(authenticated and unauthenticated). - Vulnerable Parameter:
variation(array) or custom metadata parameters sent during the "add to wishlist" process. - Authentication: None required (unauthenticated).
- Preconditions: At least one WooCommerce product must exist and be publishable.
3. Code Flow
- Entry Point: The request hits
admin-ajax.phpwithaction=wlfmc_add_to_wishlistOR aPOSTrequest is sent to any page withaction=wlfmc_wp_loaded_add_to_wishlist(handled byWLFMC_Ajax_Handler::wp_loaded_action). - Processing:
WLFMC_Ajax_Handler::add_to_wishlist()(inincludes/class-wlfmc-ajax-handler.php) is called. - Sink (Storage): The function extracts product data and variations from
$_POST. It saves these to the database (likely thewp_wlfmc_wishlist_itemstable) using raw values from thevariationarray without applyingsanitize_text_field()orwp_kses(). - Sink (Rendering): When a user or administrator views the wishlist (via the
[wlfmc_wishlist]shortcode or the admin panel), the plugin retrieves the stored variation data and echoes it into the HTML table. Becauseesc_html()oresc_attr()is missing during this output phase, the script executes.
4. Nonce Acquisition Strategy
The plugin uses wp_localize_script to pass configuration and nonces to the frontend. The scripts are enqueued on pages containing wishlist shortcodes.
- Shortcode: Identify the "Add to Wishlist" or "Wishlist" shortcode. The primary shortcode is
[wlfmc_wishlist]. - Page Creation: Use WP-CLI to create a public page containing this shortcode to ensure the script is enqueued.
- Variable Identification: The localization object is named
wlfmc_l10n. - Extraction:
- Use
browser_navigateto visit the created page. - Use
browser_evalto extract the nonce:window.wlfmc_l10n?.nonceor check thedata-nonceattribute on the wishlist table:jQuery('#wlfmc-wishlist-form table.wlfmc-wishlist-table').data('nonce'). - Based on
class-wlfmc-ajax-handler.php, the nonce action is likely-1(default) orwlfmc_add_to_wishlist.
- Use
5. Exploitation Strategy
Step 1: Data Setup
Create a product and a page to facilitate nonce extraction.
# Create a simple product
wp wc product create --name="Exploit Product" --type=simple --regular_price=10 --status=publish
# Create a page with the wishlist shortcode to expose the nonce
wp post create --post_type=page --post_title="My Wishlist" --post_status=publish --post_content="[wlfmc_wishlist]"
Step 2: Nonce Extraction
Navigate to the wishlist page and extract the nonce.
- URL:
/my-wishlist/ - JS Command:
window.wlfmc_l10n.nonce(or check the HTML source fordata-nonce).
Step 3: Payload Delivery
Send a malicious AJAX request to store the XSS payload.
- Method: POST
- URL:
http://<target>/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Parameters:
action:wlfmc_add_to_wishlistproduct_id:<ID_FROM_STEP_1>variation[pa_color]:<img src=x onerror=alert(document.domain)>nonce:<EXTRACTED_NONCE>
Step 4: Execution
The script will trigger when:
- The attacker (or any user) visits the
/my-wishlist/page. - An administrator views the "Wishlists" or "Analytics" section in the WordPress dashboard.
6. Test Data Setup
- Product ID: Required (e.g.,
10). - Shortcode Page:
/wishlist-test/containing[wlfmc_wishlist]. - Target User: Unauthenticated for injection; Admin for impact verification.
7. Expected Results
- The AJAX response should return
{"success":true,...}. - Upon visiting the wishlist page, an alert box showing the document domain should appear.
- In the database, the
variationcolumn for the new item inwp_wlfmc_wishlist_itemsshould contain the literal<img src=x...>string.
8. Verification Steps
Verify the payload is stored in the database:
wp db query "SELECT variation FROM wp_wlfmc_wishlist_items WHERE variation LIKE '%onerror%';"
Verify the output is unescaped in the frontend:
# Use http_request to fetch the wishlist page and grep for the raw payload
http_request get "http://<target>/my-wishlist/" | grep "onerror=alert"
9. Alternative Approaches
The wp_loaded Bypass
If admin-ajax.php enforces strict nonce checks that cannot be satisfied, use the wp_loaded entry point:
- Method: POST
- URL:
http://<target>/(Homepage) - Parameters:
action:wlfmc_wp_loaded_add_to_wishlistproduct_id:<ID>variation[anything]:<script>alert(1)</script>
This bypasses the standard WordPress AJAX routing and might skip certain nonce checks depending on the plugin's internal logic inwp_loaded_action.
Parameter Fuzzing
If variation is sanitized, attempt injection via:
wishlist_tokenquantity(if not cast to int)add_to_wishlist(if the product name is reflected in the success message/fragment)
Summary
The MoreConvert Wishlist for WooCommerce plugin is vulnerable to unauthenticated stored Cross-Site Scripting (XSS) because it fails to sanitize and escape product variation data when adding items to a wishlist. An attacker can inject malicious scripts into product metadata, which then execute when a user or administrator views the wishlist on the frontend or within the admin dashboard.
Vulnerable Code
/* includes/class-wlfmc-ajax-handler.php registration of unauthenticated action */ // line 35 add_action( 'wp_ajax_wlfmc_add_to_wishlist', array( 'WLFMC_Ajax_Handler', 'add_to_wishlist' ) ); add_action( 'wp_ajax_nopriv_wlfmc_add_to_wishlist', array( 'WLFMC_Ajax_Handler', 'add_to_wishlist' ) ); --- /* assets/frontend/js/main.js (approx line 1115) - JS sending data without a nonce */ var params = { action: wlfmc_l10n.actions.add_to_wishlist_action, context: 'frontend', add_to_wishlist: product_id, product_type: t.attr('data-product-type') };
Security Fix
@@ -1117,7 +1117,8 @@ action: wlfmc_l10n.actions.add_to_wishlist_action, context: 'frontend', add_to_wishlist: product_id, - product_type: t.attr('data-product-type') + product_type: t.attr('data-product-type'), + nonce: t.data('nonce') // wishlist_id: t.attr( 'data-wishlist-id' ), // fragments: retrieve_fragments( product_id ) };
Exploit Outline
1. Identify a valid WooCommerce product ID on the target site. 2. Craft a POST request to the WordPress AJAX endpoint (`/wp-admin/admin-ajax.php`) using the `wlfmc_add_to_wishlist` action. 3. In the request parameters, include the `variation` array populated with a malicious XSS payload (e.g., `variation[pa_size]=<img src=x onerror=alert(1)>`). 4. If the plugin's 'wp_loaded' AJAX mode is enabled, an alternative vector involves sending the same parameters to the homepage with the action `wlfmc_wp_loaded_add_to_wishlist`. 5. The payload will be stored in the database. When an administrator views the wishlist management or analytics pages, or when a user views the wishlist via the `[wlfmc_wishlist]` shortcode, the script will execute.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.