Customer Reviews for WooCommerce <= 5.103.0 - Unauthenticated Authentication Bypass to Arbitrary Review Submission via 'key' Parameter
Description
The Customer Reviews for WooCommerce plugin for WordPress is vulnerable to authentication bypass in all versions up to, and including, 5.103.0. This is due to the `create_review_permissions_check()` function comparing the user-supplied `key` parameter against the order's `ivole_secret_key` meta value using strict equality (`===`), without verifying that the stored key is non-empty. For orders where no review reminder email has been sent, the `ivole_secret_key` meta is not set, causing `get_meta()` to return an empty string. An attacker can supply `key: ""` to match this empty value and bypass the permission check. This makes it possible for unauthenticated attackers to submit, modify, and inject product reviews on any product — including products not associated with the referenced order — via the REST API endpoint `POST /ivole/v1/review`. Reviews are auto-approved by default since `ivole_enable_moderation` defaults to `"no"`.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=5.103.0What Changed in the Fix
Changes introduced in v5.104.0
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-4664 ## 1. Vulnerability Summary The **Customer Reviews for WooCommerce** plugin (up to 5.103.0) contains an improper authentication vulnerability in its REST API implementation. The endpoint `POST /wp-json/ivole/v1/review` uses a permission check function (`c…
Show full research plan
Exploitation Research Plan: CVE-2026-4664
1. Vulnerability Summary
The Customer Reviews for WooCommerce plugin (up to 5.103.0) contains an improper authentication vulnerability in its REST API implementation. The endpoint POST /wp-json/ivole/v1/review uses a permission check function (create_review_permissions_check) that validates access by comparing a user-provided key parameter against a specific order's meta value (ivole_secret_key).
The vulnerability exists because:
- The plugin uses strict equality (
===) for the comparison. - The
ivole_secret_keymeta is only generated when a review reminder email is sent. - For orders where no reminder has been sent,
get_post_meta()returns an empty string (""). - An attacker can provide an empty
keyparameter, which strictly matches the empty meta value, bypassing authentication.
2. Attack Vector Analysis
- Endpoint:
/wp-json/ivole/v1/review - Method:
POST - Authentication: Unauthenticated (Bypassed via
keyparameter). - Vulnerable Parameter:
key(within JSON body or query string). - Payload: A JSON object containing a valid
orderID and an array ofitemsto review. - Preconditions:
- At least one WooCommerce Order must exist in the database.
- The Order ID must be known (IDs are sequential/guessable).
- The
ivole_secret_keymeta must not have been set for that order (common for new or unprocessed orders).
3. Code Flow
- Entry Point:
CR_Endpoint::register_routes()inincludes/reviews/class-cr-endpoint.phpregisters the route/ivole/v1/review. - Permission Check: Before execution,
create_review_permissions_check()is called.- It retrieves the
order_idfrom the request. - It calls
get_post_meta( $order_id, 'ivole_secret_key', true ). - If the meta is missing, the result is
"". - It compares this against the
keyparam from the request. If"" === "", it returnstrue.
- It retrieves the
- Callback:
CR_Endpoint::create_review_callback()is executed.- It decodes the JSON body into
$body2. - It calls
self::create_review( $body2, false ).
- It decodes the JSON body into
- Sink:
CR_Endpoint::create_review()processes the review data.- It instantiates the order:
$order = new WC_Order( $order_id ). - It iterates through
$body2->order->items. - It creates a WordPress comment for each item (product) with
comment_typeset toreview. - Reviews are auto-approved if
ivole_enable_moderationis'no'(the default).
- It instantiates the order:
4. Nonce Acquisition Strategy
This specific vulnerability targets a custom REST API endpoint intended for external use (CusRev service). The permission_callback handles authorization via the key parameter. Standard WordPress REST API nonces (_wpnonce) are not required for this endpoint if the permission_callback returns true.
No nonce acquisition is necessary for this exploit.
5. Exploitation Strategy
The goal is to submit an unauthenticated review for a product by referencing a valid order ID with an empty secret key.
Step-by-Step Plan:
- Identify Targets: Find a valid Product ID and a valid Order ID.
- Prepare Payload: Create a JSON object that includes the
key(empty), theorderID, and the review details. - Send Request: Execute a POST request to the REST API.
HTTP Request Details:
- URL:
http://<target>/wp-json/ivole/v1/review - Method:
POST - Headers:
Content-Type: application/json - Body:
{
"key": "",
"order": {
"id": 123,
"items": [
{
"id": 456,
"rating": 5,
"comment": "This product was amazing! (Injected Review)"
}
]
}
}
(Replace 123 with a valid Order ID and 456 with a valid Product ID).
6. Test Data Setup
To reliably test this, the following environment state is required:
- WooCommerce Active: Must be installed and configured.
- Target Product: Create a product with ID
X.wp post create --post_type=product --post_title='Target Product' --post_status=publish
- Target Order: Create an order with ID
Ythat includes any product.wp wc shell --command="\$order = wc_create_order(); \$order->add_product(get_product(X)); \$order->set_billing_email('victim@example.com'); \$order->save();"
- Plugin Setting: Ensure moderation is off (default).
wp option update ivole_enable_moderation 'no'
7. Expected Results
- HTTP Response:
200 OKor201 Created. - Database State: A new entry in the
wp_commentstable associated with the Product ID, havingcomment_type=reviewandcomment_approved=1.
8. Verification Steps
- Check via WP-CLI:
wp comment list --post_id=<PRODUCT_ID> --status=approve - Confirm Meta: Verify that the comment has the
ratingmeta.wp comment meta list <COMMENT_ID> - UI Verification: Navigate to the product page on the frontend and check the "Reviews" tab.
9. Alternative Approaches
- Shop Review Injection: If product reviews are disabled, target the "Shop Review" feature by providing
shop_ratingandshop_commentin theorderobject instead ofitems. - Modifying Existing Reviews: The plugin description mentions "modify" reviews. This may involve providing a
comment_idin the payload if the code path supports updates (to be verified during execution by inspectingcreate_reviewlogic for existing comment checks). - Parameter Placement: If
keyin the JSON body is ignored by the permission check, try passing it as a query parameter:POST /wp-json/ivole/v1/review?key=.
Summary
The Customer Reviews for WooCommerce plugin is vulnerable to an unauthenticated authentication bypass due to an insecure comparison in the `create_review_permissions_check` function. The function compares a user-provided `key` against an order's `ivole_secret_key` meta value using strict equality without ensuring the stored key is non-empty. An attacker can exploit this by providing an empty string for the `key` parameter to match uninitialized keys, allowing them to submit or modify product reviews via the `/ivole/v1/review` REST API endpoint.
Vulnerable Code
// includes/reviews/class-cr-endpoint.php lines 646-662 public function create_review_permissions_check( WP_REST_Request $request ) { $body = $request->get_body(); $body2 = json_decode( $body ); if( json_last_error() === JSON_ERROR_NONE ) { if( isset( $body2->key ) && isset( $body2->order ) ) { if( isset( $body2->order->id ) ) { $order = wc_get_order( $body2->order->id ); if ( $order ) { $saved_key = $order->get_meta( 'ivole_secret_key', true ); if( $body2->key === $saved_key ) { return true; } else {
Security Fix
@@ -646,13 +646,13 @@ public function create_review_permissions_check( WP_REST_Request $request ) { $body = $request->get_body(); $body2 = json_decode( $body ); - if( json_last_error() === JSON_ERROR_NONE ) { - if( isset( $body2->key ) && isset( $body2->order ) ) { - if( isset( $body2->order->id ) ) { + if ( json_last_error() === JSON_ERROR_NONE ) { + if ( isset( $body2->key ) && isset( $body2->order ) ) { + if ( isset( $body2->order->id ) ) { $order = wc_get_order( $body2->order->id ); if ( $order ) { $saved_key = $order->get_meta( 'ivole_secret_key', true ); - if( $body2->key === $saved_key ) { + if ( ! empty( $saved_key ) && $body2->key === $saved_key ) { return true; } else { return new WP_Error(
Exploit Outline
To exploit this vulnerability, an unauthenticated attacker identifies a valid WooCommerce Order ID (IDs are typically sequential and guessable). Because the plugin only generates a secret key when a review reminder email is sent, many orders (like newly created or processed ones) will have an empty string stored for the `ivole_secret_key` meta. The attacker sends a POST request to `/wp-json/ivole/v1/review` with a JSON payload where the `key` parameter is an empty string and the `order` object contains the target Order ID. By providing a product ID in the `items` array within that payload, the attacker can successfully submit a review. If the default moderation setting (`ivole_enable_moderation`) is 'no', the review is automatically approved and displayed on the site.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.