User Registration & Membership <= 5.1.5 - Unauthenticated Missing Authorization to Admin Approval Bypass via 'action' Parameter
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:NTechnical Details
<=5.1.5What Changed in the Fix
Changes introduced in v5.1.6
Source Code
WordPress.org SVN# 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
POSTrequest to any frontend page containing a[user_registration_form]shortcode or theadmin-ajax.phpendpoint. - Vulnerable Parameter:
action=createuser(added to the$_REQUEST/$_POSTbody). - 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
- A user submits a registration form on the frontend.
- The plugin's form handler (likely in
includes/class-ur-frontend-form-handler.php) catches thePOSTrequest. - During the user creation process, the plugin determines the initial user status (e.g.,
active,pending). - The plugin calls
is_admin_creation_process()(often located in a utility or main class). - Vulnerable Logic:
public function is_admin_creation_process() { if ( isset( $_REQUEST['action'] ) && 'createuser' === $_REQUEST['action'] ) { return true; // Vulnerability: No capability check here. } return false; } - If it returns
true, the plugin assigns the user an "Approved" status immediately, bypassing the configuredadmin_approvalrequirement. - 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.
- Identify Shortcode: The plugin uses
[user_registration_form id="<ID>"]. - Setup Page: Create a page with a known form ID.
- Variable Name: The plugin localizes data into the
user_registration_paramsobject. - Nonce Key: The key is typically
ur_frontend_form_nonce. - 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_useruser_email_<ID>:attacker@example.comuser_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
- Create Form: Use WP-CLI to ensure a form exists (or use the default form created upon installation).
wp post list --post_type=user_registrationto find the form ID.
- Configure Approval: Set the plugin option to require admin approval.
wp option update user_registration_general_setting_login_options admin_approval
- Create Page:
wp post create --post_type=page --post_title="Register" --post_status=publish --post_content='[user_registration_form id="<FORM_ID>"]'
- Extract Form Fields: Navigate to the page and inspect the
inputnames within the<form>.
7. Expected Results
- Normal Registration (Without Payload): The response indicates the user is "under approval" or "pending." The
wp_userstable shows the user, butwp_usermetashows auser_statusofpending. - 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:
- Check User Existence:
wp user get attacker_user
- Check Approval Status:
wp user meta get attacker_user user_registration_status- Expected Result: If the value is
approvedor empty (depending on version logic) instead ofpending, the bypass was successful.
- Attempt Login:
- Try to authenticate via
wp-login.phpwith the new credentials.
- Try to authenticate via
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=createuserBody: 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.
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
@@ -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.