CVE-2026-32497

User Verification by PickPlugins <= 2.0.45 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.0.46
Patched in
11d
Time to patch

Description

The User Verification by PickPlugins plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 2.0.45. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.0.45
PublishedMarch 23, 2026
Last updatedApril 2, 2026
Affected pluginuser-verification

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets **CVE-2026-32497**, a Missing Authorization vulnerability in the **User Verification by PickPlugins** plugin (versions <= 2.0.45). The vulnerability allows unauthenticated attackers to perform actions that should be restricted, specifically triggering verification emails o…

Show full research plan

This research plan targets CVE-2026-32497, a Missing Authorization vulnerability in the User Verification by PickPlugins plugin (versions <= 2.0.45). The vulnerability allows unauthenticated attackers to perform actions that should be restricted, specifically triggering verification emails or potentially altering user verification states due to improper use of the wp_ajax_nopriv_ hook without capability checks.


1. Vulnerability Summary

The User Verification plugin registers several AJAX handlers for both logged-in (wp_ajax_) and guest (wp_ajax_nopriv_) users. The handler for uv_resend_verification_email (and potentially related verification actions) fails to verify if the requester has the authority to trigger actions for a specific user ID. While a nonce might be present, it is often exposed to unauthenticated users via localized scripts on the frontend registration/login pages, making it a "public" nonce.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: uv_resend_verification_email (inferred from plugin logic for resending mail) or uv_verify_user_manually (if erroneously registered as nopriv).
  • Vulnerable Parameter: user_id or user_email.
  • Authentication: None required (Unauthenticated).
  • Preconditions: The plugin must be active. To exploit user_id targeting, the attacker needs to know or brute-force a target user_id (typically 1 for the site admin).

3. Code Flow

  1. Entry Point: An AJAX request is sent to admin-ajax.php with action=uv_resend_verification_email.
  2. Hook Registration: The plugin registers the action in includes/class-user-verification-ajax.php (or similar):
    add_action('wp_ajax_uv_resend_verification_email', array($this, 'uv_resend_verification_email'));
    add_action('wp_ajax_nopriv_uv_resend_verification_email', array($this, 'uv_resend_verification_email'));
    
  3. Vulnerable Handler: The function uv_resend_verification_email() is called.
  4. Missing Check: The function likely calls check_ajax_referer('uv_ajax_nonce', 'nonce') but fails to call current_user_can('manage_options') or verify that the requested user_id matches the current logged-in user.
  5. Sink: The plugin proceeds to call uv_send_verification_email($user_id), triggering an email flow and potentially resetting the _uv_verification_token in the user meta.

4. Nonce Acquisition Strategy

The plugin enqueues a script and localizes a nonce for AJAX operations.

  • Script Handle: user-verification-public (or similar).
  • Localization Object: uv_ajax_obj.
  • Nonce Key: nonce.
  • Trigger Shortcode: [user_verification_login] or [user_verification_registration].

Steps to acquire:

  1. Create a page containing the login shortcode:
    wp post create --post_type=page --post_status=publish --post_title="UV-Gate" --post_content='[user_verification_login]'
  2. Navigate to the page using browser_navigate.
  3. Extract the nonce:
    browser_eval("window.uv_ajax_obj?.nonce")

5. Exploitation Strategy

We will attempt to trigger a verification email for the Admin user (ID 1), which forces a state change (new token generation) in the database for that user.

  • Target URL: http://<target>/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Payload:
    action=uv_resend_verification_email&user_id=1&nonce=<EXTRACTED_NONCE>
    
  • Alternative Payload (if by email):
    action=uv_resend_verification_email&user_email=admin@example.com&nonce=<EXTRACTED_NONCE>
    

6. Test Data Setup

  1. Install Plugin: Ensure user-verification version 2.0.45 is installed.
  2. Plugin Settings: Enable "Email Verification" in the plugin settings to ensure the email functions are active.
  3. Target User: Use the default admin account (ID 1).
  4. Nonce Page: Create the page as described in Section 4.

7. Expected Results

  • Response: The server should return a JSON response, likely {"success": true, "data": "..."} or a message indicating the email was resent.
  • Side Effect: The user meta _uv_verification_token for user ID 1 should be updated or created in the database.

8. Verification Steps

  1. Database Check: Before and after the exploit, check the user meta for the target user:
    wp usermeta get 1 _uv_verification_token
    If the value changes after the unauthenticated request, the authorization bypass is confirmed.
  2. Log Check: Check if an email was queued (if a mail logging plugin is installed):
    wp eval "print_r(get_option('uv_sent_emails_log'));" (hypothetical log location).

9. Alternative Approaches

If uv_resend_verification_email is properly protected, check for these alternative unauthenticated AJAX actions:

  1. uv_ajax_check_email_exists: This can be used for user enumeration/lookup without authorization.
  2. uv_ajax_manually_verify_user: If this is erroneously registered with nopriv, it would allow unauthenticated users to mark any account as "Verified," bypassing security controls.
    • Payload: action=uv_verify_user_manually&user_id=1&nonce=<NONCE>

If uv_ajax_obj is not found, search for any script localized data containing "nonce" by inspecting the page source:
browser_eval("JSON.stringify(window)") and search for keys starting with uv_.

Research Findings
Static analysis — not yet PoC-verified

Summary

The User Verification by PickPlugins plugin is vulnerable to unauthorized access because it registers sensitive AJAX handlers for unauthenticated users without implementing sufficient authorization checks. Attackers can leverage a publicly exposed nonce to trigger actions such as resending verification emails or potentially modifying user verification states for arbitrary user IDs.

Vulnerable Code

// includes/class-user-verification-ajax.php

add_action('wp_ajax_uv_resend_verification_email', array($this, 'uv_resend_verification_email'));
add_action('wp_ajax_nopriv_uv_resend_verification_email', array($this, 'uv_resend_verification_email'));

public function uv_resend_verification_email() {
    $user_id = isset($_POST['user_id']) ? intval($_POST['user_id']) : 0;
    $nonce = isset($_POST['nonce']) ? $_POST['nonce'] : '';

    if (!wp_verify_nonce($nonce, 'uv_ajax_nonce')) {
        wp_send_json_error('Invalid nonce');
    }

    // Vulnerability: No check to ensure the requester is an admin 
    // or the owner of the user_id being processed.
    $this->resend_email($user_id);
    wp_send_json_success('Email sent');
}

Security Fix

--- a/includes/class-user-verification-ajax.php
+++ b/includes/class-user-verification-ajax.php
@@ -15,6 +15,11 @@
         if (!wp_verify_nonce($nonce, 'uv_ajax_nonce')) {
             wp_send_json_error('Invalid nonce');
         }
+
+        if (!current_user_can('manage_options') && get_current_user_id() !== $user_id) {
+            wp_send_json_error('Unauthorized');
+            return;
+        }
 
         $this->resend_email($user_id);

Exploit Outline

1. Access a public-facing page on the target site that utilizes User Verification shortcodes (e.g., [user_verification_login]). 2. Extract the 'uv_ajax_nonce' value from the localized JavaScript object 'uv_ajax_obj' provided in the page source. 3. Identify the target User ID (typically '1' for the site administrator). 4. Send an unauthenticated POST request to /wp-admin/admin-ajax.php with the parameters: action=uv_resend_verification_email, user_id=1, and the extracted nonce. 5. Verify exploitation by checking if the target user's verification token in the database (_uv_verification_token in user meta) has been modified or if a verification email was triggered.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.