ReviewX – WooCommerce Product Reviews with Multi-Criteria, Reminder Emails, Google Reviews, Schema & More <= 2.2.12 - Unauthenticated Sensitive Information Exposure
Description
The ReviewX – WooCommerce Product Reviews with Multi-Criteria, Reminder Emails, Google Reviews, Schema & More plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 2.2.12 via the syncedData function. This makes it possible for unauthenticated attackers to extract sensitive data including user names, emails, phone numbers, addresses.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
What Changed in the Fix
Changes introduced in v2.3.0
Source Code
WordPress.org SVNThis plan outlines the research and exploitation strategy for **CVE-2025-10734**, a sensitive information exposure vulnerability in the **ReviewX** plugin (<= 2.2.12). ### 1. Vulnerability Summary The vulnerability exists in the `syncedData` function, which is exposed via the plugin's REST API. Due…
Show full research plan
This plan outlines the research and exploitation strategy for CVE-2025-10734, a sensitive information exposure vulnerability in the ReviewX plugin (<= 2.2.12).
1. Vulnerability Summary
The vulnerability exists in the syncedData function, which is exposed via the plugin's REST API. Due to a lack of authentication and authorization checks, any user (unauthenticated) can call this endpoint. The function is designed to facilitate data synchronization between the WordPress site and the ReviewX SaaS platform (reviewx.io). It retrieves and returns detailed information about product reviews, including sensitive Personal Identifiable Information (PII) of the reviewers such as full names, email addresses, and potentially phone numbers or addresses linked to WooCommerce orders.
2. Attack Vector Analysis
- Endpoint: Inferred to be a REST API route under the
reviewx/v1namespace (likely/wp-json/reviewx/v1/synced-dataor/wp-json/reviewx/v1/sync). - HTTP Method:
GET(most likely for data extraction). - Authentication: None required (
PR:N). - Preconditions: The plugin must be active. For the data to be "sensitive," there must be existing reviews in the system.
3. Code Flow (Inferred)
- Registration: The plugin registers a REST route during the
rest_api_inithook. - Route Mapping: The route (e.g.,
synced-data) is mapped to a callback method namedsyncedDatawithin a REST controller class. - Missing Permission Check: The
register_rest_routecall likely lacks apermission_callbackor uses__return_true, allowing unauthenticated access. - Data Retrieval: The
syncedDatafunction queries thewp_commentsandwp_commentmetatables (and possiblywp_postsfor WooCommerce order data). - Sink: The function returns a
WP_REST_Responsecontaining a JSON array of reviewer details:comment_author(User Name)comment_author_email(Email)- WooCommerce billing data (Phone/Address) if the review is verified/linked to an order.
4. Nonce Acquisition Strategy
Based on the "Unauthenticated" nature of this vulnerability and the likely purpose of the endpoint (SaaS synchronization), it is highly probable that no WordPress nonce is required.
However, if a nonce is required for the REST API (wp_rest), it can be obtained as follows:
- Identify Shortcode: ReviewX commonly uses the
[reviewx_pagination]or[reviewx_reviews]shortcodes. - Setup Page: Create a public page containing one of these shortcodes.
- Extract Nonce:
- Navigate to the page using
browser_navigate. - Execute
browser_eval("window.rvx_params?.nonce")orbrowser_eval("window.rvx_params?.rest_nonce"). - The localization key is often
rvx_paramsorreviewx_data.
- Navigate to the page using
5. Exploitation Strategy
Step 1: Identify the Endpoint
Query the WordPress REST API index to find the exact ReviewX route mapping.
- Action:
http_request - Method:
GET - URL:
/wp-json/reviewx/v1 - Goal: Look for routes containing "sync" or "data" and identify the callback associated with
syncedData.
Step 2: Populate Target Data
To confirm exposure, the environment must contain reviews with PII.
- Action: Use WP-CLI to create a WooCommerce product and multiple reviews.
wp eval " \$product_id = wc_create_product(['name' => 'Vulnerable Product']); wp_insert_comment([ 'comment_post_ID' => \$product_id, 'comment_author' => 'John Doe', 'comment_author_email' => 'john.doe@example.com', 'comment_content' => 'Great product!', 'comment_type' => 'review', 'comment_approved' => 1 ]); "
Step 3: Execute Data Extraction
Perform the unauthenticated request to the identified endpoint.
- Action:
http_request - Method:
GET - URL:
/wp-json/reviewx/v1/synced-data(or the route found in Step 1). - Headers:
Accept: application/json
Step 4: Verify PII in Response
Check the JSON response for the email john.doe@example.com and the name John Doe.
6. Test Data Setup
- Plugin Status: Ensure
reviewxversion 2.2.12 is installed and active. - WooCommerce: WooCommerce must be active as ReviewX depends on it.
- Reviews:
- Create a "Guest" review (author name/email).
- Create a "Customer" review (linked to a WP User).
- (Optional) Use WP-CLI to add meta keys like
_billing_phoneto the user to see if thesyncedDatafunction pulls extended profile data.
7. Expected Results
- Vulnerable Response: A
200 OKstatus with a JSON body containing an array of review objects. Each object includes cleartextcomment_author_emailandcomment_author. - Example Payload Snippet:
[ { "wp_id": 123, "reviewer_name": "John Doe", "reviewer_email": "john.doe@example.com", "feedback": "Great product!", "rating": 5 } ]
8. Verification Steps
- Check Output: Verify that the email and name in the HTTP response match the data created in the "Test Data Setup" step.
- Verify Unauthenticated Status: Perform the request without any cookies or
Authorizationheaders to confirm the "Unauthenticated" claim. - Confirm Version: Use
wp plugin get reviewx --field=versionto ensure the test was performed on <= 2.2.12.
9. Alternative Approaches
If /synced-data is not the route:
- Route Discovery: Iterate through all routes returned by
/wp-json/reviewx/v1. - Parameter Fuzzing: Some sync functions require a
last_sync_idortimestamp. Try?since=0or?page=1if the initial request returns an empty array. - Check Admin-Ajax: ReviewX also registers many
wp_ajax_nopriv_actions. Search the codebase foradd_action('wp_ajax_nopriv_to see ifsyncedDatais also exposed via AJAX.- Target:
/wp-admin/admin-ajax.php?action=rvx_get_synced_data(inferred).
- Target:
Summary
The ReviewX plugin for WordPress (<= 2.2.12) is vulnerable to unauthenticated sensitive information exposure through its data synchronization REST API endpoint. The `syncedData` function lacks proper authentication and authorization checks, allowing any user to retrieve reviewer PII, including names, email addresses, and WooCommerce billing details.
Security Fix
@@ -35,6 +35,6 @@ */ public function getDefaultHeaders() : array { - return ['Authorization' => 'Bearer ' . Helper::getAuthToken(), 'X-Auth-Token' => 'Bearer ' . Helper::getAuthToken(), 'Accept' => 'application/json', 'X-Domain' => Helper::getWpDomainNameOnly(), 'X-Theme' => wp_get_theme()->get('Name'), 'X-Site-Locale' => get_locale(), 'X-Request-Id' => \sha1(\time() . Client::getUid()), 'X-Wp-Version' => get_bloginfo("version"), 'X-Reviewx-Version' => RVX_VERSION, 'X-Environment' => Helper::plugin()->isProduction() ? 'production' : 'development']; + return ['Accept' => 'application/json', 'Authorization' => 'Bearer ' . Helper::getAuthToken(), 'X-Domain' => Helper::getWpDomainNameOnly(), 'X-Theme' => wp_get_theme()->get('Name'), 'X-Site-Locale' => get_locale(), 'X-Request-Id' => \sha1(\time() . Client::getUid()), 'X-Wp-Version' => get_bloginfo("version"), 'X-Reviewx-Version' => RVX_VERSION, 'X-Environment' => Helper::plugin()->isProduction() ? 'production' : 'development']; } } @@ -72,7 +72,6 @@ $headers = ['Content-Type' => 'application/json']; if ($this->token) { $headers['Authorization'] = 'Bearer ' . $this->token; - $headers['X-Auth-Token'] = 'Bearer ' . $this->token; } return $headers; } ... (truncated)
Exploit Outline
1. Query the WordPress REST API index to identify the ReviewX route mapping, typically located under the '/wp-json/reviewx/v1' namespace. 2. Locate the endpoint associated with the 'syncedData' function (e.g., '/wp-json/reviewx/v1/synced-data' or '/wp-json/reviewx/v1/sync'). 3. Execute an unauthenticated GET request to the identified endpoint. No WordPress nonces or authorization headers are required. 4. Analyze the JSON response, which returns an array of review data objects containing sensitive fields like 'comment_author' (name), 'comment_author_email', and linked WooCommerce billing information (phone and address) for verified customers.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.