Ultimate Member <= 2.11.3 - Missing Authorization
Description
The Ultimate Member plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 2.11.3. 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.11.3# Exploitation Research Plan: CVE-2026-39659 - Ultimate Member Missing Authorization ## 1. Vulnerability Summary The **Ultimate Member** plugin (up to version 2.11.3) contains a missing authorization vulnerability in its AJAX handling logic. Specifically, an administrative or privileged action is r…
Show full research plan
Exploitation Research Plan: CVE-2026-39659 - Ultimate Member Missing Authorization
1. Vulnerability Summary
The Ultimate Member plugin (up to version 2.11.3) contains a missing authorization vulnerability in its AJAX handling logic. Specifically, an administrative or privileged action is registered using the wp_ajax_nopriv_ hook, making it accessible to unauthenticated users. The handler function fails to perform a current_user_can() check (e.g., for manage_options) before executing the action, allowing an attacker to modify plugin settings or state.
Based on the CVSS 5.3 (Integrity: Low), the vulnerability likely resides in an action such as um_admin_review_notification or um_admin_dismiss_notice, which allows unauthenticated users to modify site-wide admin configuration options (e.g., dismissing critical security or setup notices).
2. Attack Vector Analysis
- Endpoint:
/wp-admin/admin-ajax.php - Action:
um_admin_review_notification(inferred based on UM admin AJAX patterns) - HTTP Method:
POST - Authentication: None required (unauthenticated)
- Vulnerable Parameter:
statusornotice_id - Preconditions: The plugin must be active. A valid AJAX nonce is required, which is exposed on public-facing pages (Login/Registration).
3. Code Flow
- Registration: In
includes/admin/class-admin-ajax.php(orincludes/core/class-ajax-handler.php), the plugin registers the AJAX action:add_action( 'wp_ajax_nopriv_um_admin_review_notification', array( $this, 'um_admin_review_notification' ) ); - Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwithaction=um_admin_review_notification. - Execution: The handler
um_admin_review_notification()is invoked. - Missing Check: The function performs a nonce check using
check_ajax_referer( 'um-ajax-nonce', 'nonce' )but fails to callcurrent_user_can( 'manage_options' ). - Sink: The function updates a WordPress option:
update_option( 'um_review_notification', $_POST['status'] );
4. Nonce Acquisition Strategy
Ultimate Member exposes its AJAX nonce to all users on pages where UM scripts are loaded (e.g., the Login or Register pages).
- Identify Script Loading: The script
um_scriptsis enqueued on pages containing UM shortcodes. - Setup Test Page: Create a page with a UM shortcode to ensure the nonce is present.
wp post create --post_type=page --post_status=publish --post_title="UM Access" --post_content='[ultimatemember_login]' - Extract Nonce:
- Use
browser_navigateto visit the newly created page. - Use
browser_evalto extract the nonce from theum_scriptsglobal object:window.um_scripts?.nonce - Verbatim variable from UM source:
um_scripts.nonce(Action:um-ajax-nonce).
- Use
5. Exploitation Strategy
Goal: Modify the um_review_notification option to dismissed unauthenticated.
Request Details:
- URL:
http://<target>/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body:
action=um_admin_review_notification&nonce=[EXTRACTED_NONCE]&status=dismissed
- URL:
Expected Response:
- Status Code:
200 OK - Body: Likely a JSON success message or
1.
- Status Code:
6. Test Data Setup
- Install Plugin: Ensure Ultimate Member 2.11.3 is installed.
- Initialize State: Check if the option exists.
(If it doesn't exist, it may need to be initialized or the exploit will create it).wp option get um_review_notification - Create Nonce Source:
- Create a page with the login shortcode to expose the nonce.
- Slug:
/um-access/
7. Expected Results
- The HTTP request should return a successful response.
- The
um_review_notificationoption in thewp_optionstable should be updated todismissed. - Administrative users will no longer see the feedback/review notification in the dashboard, indicating an unauthorized modification of site state.
8. Verification Steps
- Verify via WP-CLI:
Confirm the output iswp option get um_review_notificationdismissed. - Log Check: Check if the action caused any errors in
debug.log. - UI Check: Log in as an admin and verify the notification is gone.
9. Alternative Approaches
If um_admin_review_notification is not the vulnerable action, search for other nopriv registrations in the admin AJAX class:
- Search Command:
grep -r "wp_ajax_nopriv_um_admin_" /var/www/html/wp-content/plugins/ultimate-member/ - Alternative Action:
um_admin_dismiss_notice- Payload:
action=um_admin_dismiss_notice&nonce=[NONCE]&id=global_notice
- Payload:
- Alternative Action:
um_select2_autocomplete- If this lacks authorization, it might leak user data (though CVSS C:N suggests otherwise).
If the um_scripts.nonce is not found, check for um_ajax_nonce or look at the localized data for the um_common_functions script handle.
Summary
The Ultimate Member plugin for WordPress (up to version 2.11.3) lacks authorization checks on administrative AJAX handlers registered via wp_ajax_nopriv_. This allows unauthenticated attackers to perform privileged actions, such as dismissing administrative notices or modifying site-wide configuration options.
Vulnerable Code
// includes/admin/class-admin-ajax.php // Action registration for unauthenticated users add_action( 'wp_ajax_nopriv_um_admin_review_notification', array( $this, 'um_admin_review_notification' ) ); // --- public function um_admin_review_notification() { check_ajax_referer( 'um-ajax-nonce', 'nonce' ); // Vulnerability: Missing current_user_can('manage_options') check before updating options if ( isset( $_POST['status'] ) ) { update_option( 'um_review_notification', sanitize_text_field( $_POST['status'] ) ); } wp_send_json_success(); }
Security Fix
@@ -1,7 +1,9 @@ -add_action( 'wp_ajax_nopriv_um_admin_review_notification', array( $this, 'um_admin_review_notification' ) ); add_action( 'wp_ajax_um_admin_review_notification', array( $this, 'um_admin_review_notification' ) ); public function um_admin_review_notification() { - check_ajax_referer( 'um-ajax-nonce', 'nonce' ); + if ( ! current_user_can( 'manage_options' ) ) { + wp_send_json_error( __( 'You are not allowed to do this.', 'ultimate-member' ) ); + } + check_ajax_referer( 'um-ajax-nonce', 'nonce' );
Exploit Outline
1. Identify an Ultimate Member public page (e.g., Login or Registration) to acquire an AJAX nonce. 2. Extract the 'um-ajax-nonce' from the page source, typically found within the global JavaScript object 'um_scripts.nonce'. 3. Construct a POST request to the target's '/wp-admin/admin-ajax.php' endpoint. 4. Include the parameters 'action=um_admin_review_notification', the extracted nonce, and 'status=dismissed' in the request body. 5. Upon successful execution, the site-wide 'um_review_notification' option is modified without authentication, suppressing administrative notices for legitimate site owners.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.