CVE-2026-6145

User Registration & Membership <= 5.1.5 - Unauthenticated Missing Authorization to Admin Approval Bypass via 'action' Parameter

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
5.1.6
Patched in
1d
Time to patch

Description

The User Registration & Membership plugin for WordPress is vulnerable to Missing Authorization in all versions up to, and including, 5.1.5. This is due to the is_admin_creation_process() method relying solely on the presence of action=createuser in the $_REQUEST superglobal without performing any authentication or capability check. This makes it possible for unauthenticated attackers to bypass the admin approval requirement when registering new accounts via the fallback submission path.

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<=5.1.5
PublishedMay 13, 2026
Last updatedMay 14, 2026
Affected pluginuser-registration

What Changed in the Fix

Changes introduced in v5.1.6

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-6145 ## 1. Vulnerability Summary The **User Registration & Membership** plugin (up to 5.1.5) contains a missing authorization vulnerability within its registration logic. The plugin's internal helper method `is_admin_creation_process()` is used to determine i…

Show full research plan

Exploitation Research Plan - CVE-2026-6145

1. Vulnerability Summary

The User Registration & Membership plugin (up to 5.1.5) contains a missing authorization vulnerability within its registration logic. The plugin's internal helper method is_admin_creation_process() is used to determine if a registration request originates from the WordPress admin dashboard (e.g., an administrator manually creating a user). If this method returns true, the plugin bypasses "Admin Approval" requirements and "Email Confirmation" steps, assuming the user is being created by a trusted authority.

The vulnerability exists because is_admin_creation_process() relies solely on checking if the action parameter in the $_REQUEST superglobal is set to createuser. It performs no capability checks (current_user_can) or authentication verification. An unauthenticated attacker can include action=createuser in a standard frontend registration request to bypass administrative oversight.

2. Attack Vector Analysis

  • Endpoint: The "fallback submission path," which is a POST request to any frontend page containing a [user_registration_form] shortcode or the admin-ajax.php endpoint.
  • Vulnerable Parameter: action=createuser (added to the $_REQUEST / $_POST body).
  • Authentication: None (Unauthenticated).
  • Preconditions:
    • The plugin must have a registration form published on a page.
    • "User Login Option" in settings should ideally be set to "Admin Approval" or "Email Confirmation" to demonstrate the bypass.

3. Code Flow

  1. A user submits a registration form on the frontend.
  2. The plugin's form handler (likely in includes/class-ur-frontend-form-handler.php) catches the POST request.
  3. During the user creation process, the plugin determines the initial user status (e.g., active, pending).
  4. The plugin calls is_admin_creation_process() (often located in a utility or main class).
  5. Vulnerable Logic:
    public function is_admin_creation_process() {
        if ( isset( $_REQUEST['action'] ) && 'createuser' === $_REQUEST['action'] ) {
            return true; // Vulnerability: No capability check here.
        }
        return false;
    }
    
  6. If it returns true, the plugin assigns the user an "Approved" status immediately, bypassing the configured admin_approval requirement.
  7. The user is created and can log in immediately.

4. Nonce Acquisition Strategy

The User Registration plugin uses a nonce to protect form submissions. This nonce is localized for the frontend.

  1. Identify Shortcode: The plugin uses [user_registration_form id="<ID>"].
  2. Setup Page: Create a page with a known form ID.
  3. Variable Name: The plugin localizes data into the user_registration_params object.
  4. Nonce Key: The key is typically ur_frontend_form_nonce.
  5. Acquisition via browser_eval:
    window.user_registration_params?.ur_frontend_form_nonce
    

5. Exploitation Strategy

Step 1: Configuration

Ensure the plugin is configured to require admin approval for new users.

Step 2: Form Discovery

Identify the required field names for a specific form. Fields are usually prefixed with the field type and suffixed with the form ID (e.g., user_login_100, user_email_100).

Step 3: Payload Construction

Construct a POST request mimicking a regular registration but adding the action parameter.

Request Details:

  • Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php (or the URL of the page containing the form).
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • user_login_<ID>: attacker_user
    • user_email_<ID>: attacker@example.com
    • user_pass_<ID>: Password123!
    • ur_frontend_form_nonce: <EXTRACTED_NONCE>
    • form_id: <ID>
    • action: createuser <-- The Bypass Payload

Step 4: Execution

Submit the request using the http_request tool.

6. Test Data Setup

  1. Create Form: Use WP-CLI to ensure a form exists (or use the default form created upon installation).
    • wp post list --post_type=user_registration to find the form ID.
  2. Configure Approval: Set the plugin option to require admin approval.
    • wp option update user_registration_general_setting_login_options admin_approval
  3. Create Page:
    • wp post create --post_type=page --post_title="Register" --post_status=publish --post_content='[user_registration_form id="<FORM_ID>"]'
  4. Extract Form Fields: Navigate to the page and inspect the input names within the <form>.

7. Expected Results

  • Normal Registration (Without Payload): The response indicates the user is "under approval" or "pending." The wp_users table shows the user, but wp_usermeta shows a user_status of pending.
  • Exploited Registration (With action=createuser): The response indicates successful registration/login. The user is created with an "Approved" status.

8. Verification Steps

After sending the POST request, verify the user's status using WP-CLI:

  1. Check User Existence:
    • wp user get attacker_user
  2. Check Approval Status:
    • wp user meta get attacker_user user_registration_status
    • Expected Result: If the value is approved or empty (depending on version logic) instead of pending, the bypass was successful.
  3. Attempt Login:
    • Try to authenticate via wp-login.php with the new credentials.

9. Alternative Approaches

If the admin-ajax.php route is blocked or requires a different action string for routing (e.g., user_registration_user_register_ajax), the action=createuser parameter can be sent as a query string parameter while the registration action is sent in the POST body:

POST /wp-admin/admin-ajax.php?action=createuser
Body: action=user_registration_user_register_ajax&...

Alternatively, if the "fallback path" is targeted (standard POST to a page), the action parameter should be included in the POST body alongside the form fields. This is often the more reliable path for this specific vulnerability as it targets the non-AJAX processing logic where is_admin_creation_process() is most likely to be invoked without a conflicting routing action.

Research Findings
Static analysis — not yet PoC-verified

Summary

The User Registration & Membership plugin for WordPress (up to 5.1.5) fails to validate administrative privileges in its `is_admin_creation_process()` helper method. Unauthenticated attackers can include an `action=createuser` parameter in a standard registration request to bypass 'Admin Approval' and 'Email Confirmation' settings, resulting in immediate account activation.

Vulnerable Code

// Potential path: includes/class-user-registration.php
public function is_admin_creation_process() {
    if ( isset( $_REQUEST['action'] ) && 'createuser' === $_REQUEST['action'] ) {
        return true; // Vulnerability: No capability check here.
    }
    return false;
}

Security Fix

--- a/includes/class-user-registration.php
+++ b/includes/class-user-registration.php
@@ -1015,7 +1015,7 @@
 	public function is_admin_creation_process() {
-		if ( isset( $_REQUEST['action'] ) && 'createuser' === $_REQUEST['action'] ) {
+		if ( isset( $_REQUEST['action'] ) && 'createuser' === $_REQUEST['action'] && current_user_can( 'create_users' ) ) {
 			return true;
 		}
 
 		return false;

Exploit Outline

An unauthenticated attacker identifies a frontend registration page and extracts the `ur_frontend_form_nonce` from the `user_registration_params` localized script object. They then send a POST request to either the page URL or `admin-ajax.php` containing the standard registration fields (e.g., `user_login_<ID>`) plus the parameter `action=createuser`. This payload causes the `is_admin_creation_process()` check to return true because it only checks for the presence of the string 'createuser' in the request without verifying the user's capabilities. As a result, the plugin bypasses the 'Admin Approval' requirement and immediately activates the account.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.