CVE-2026-9178

WP Forms Connector <= 1.8 - Missing Authorization to Unauthenticated Information Exposure via 'user/list' REST Endpoint

highMissing Authorization
7.5
CVSS Score
7.5
CVSS Score
high
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The WP Forms Connector plugin for WordPress is vulnerable to Information Exposure in all versions up to, and including, 1.8. The plugin registers the REST route wp/v3/user/list/<id> (callback userDetail()) with permission_callback set to '__return_true', and the function's home-grown authentication only verifies that the supplied 'Username' HTTP header maps to an administrator account and that a 'Password' HTTP header is non-empty. It never validates the password with wp_check_password() (unlike the sibling delete_wc_user() function which does). This makes it possible for unauthenticated attackers to retrieve sensitive information for any registered user ID — including the WordPress password hash (user_pass) and email address — by sending a request with a valid administrator login name (commonly the default 'admin') and any arbitrary password value.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.8
PublishedJune 23, 2026
Last updatedJune 24, 2026
Affected pluginwp-forms-connector
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-9178 (WP Forms Connector) ## 1. Vulnerability Summary The **WP Forms Connector** plugin (<= 1.8) for WordPress suffers from a critical information exposure vulnerability due to a flawed "home-grown" authentication mechanism in its REST API implementation. The …

Show full research plan

Exploitation Research Plan: CVE-2026-9178 (WP Forms Connector)

1. Vulnerability Summary

The WP Forms Connector plugin (<= 1.8) for WordPress suffers from a critical information exposure vulnerability due to a flawed "home-grown" authentication mechanism in its REST API implementation. The plugin registers a custom REST route wp/v3/user/list/<id> designed to provide user details. While it implements a check for a Username and Password header, it only verifies that the provided Username belongs to an administrator and that the Password header is not empty. It fails to call wp_check_password() to validate the password's correctness. Because the permission_callback is set to __return_true, the endpoint is publicly accessible, allowing unauthenticated attackers to dump sensitive user data, including WordPress password hashes and email addresses.

2. Attack Vector Analysis

  • Endpoint: /wp-json/wp/v3/user/list/<id> (where <id> is the target user's ID).
  • Method: GET (Inferred based on standard REST "list" and "detail" patterns described).
  • Vulnerable Function: userDetail() (callback for the route).
  • Required Headers:
    • Username: A valid administrator login name (e.g., admin).
    • Password: Any non-empty string (e.g., pwned).
  • Authentication Level: Unauthenticated.
  • Preconditions:
    1. Knowledge of at least one administrator's username (standard WordPress reconnaissance).
    2. The plugin must be active.

3. Code Flow

  1. Registration: The plugin uses register_rest_route during rest_api_init.
    • Route: wp/v3/user/list/(?P<id>[\d]+)
    • Callback: userDetail
    • Permission Callback: __return_true
  2. Request Handling: An attacker sends a request to the endpoint.
  3. Authentication Bypass:
    • userDetail() retrieves the Username and Password headers.
    • It looks up the user by Username using get_user_by( 'login', $username ).
    • It checks if this user has the administrator capability/role.
    • It checks if ( ! empty( $password ) ).
    • The Flaw: Crucially, it skips wp_check_password( $password, $user->user_pass, $user->ID ).
  4. Data Extraction: The function retrieves the user object for the requested <id> via get_userdata( $id ).
  5. Sink: The function returns the entire user object or a subset including user_pass and user_email in a JSON response.

4. Nonce Acquisition Strategy

According to the vulnerability description, the permission_callback for this route is set to __return_true.

  • Result: No WordPress REST API nonce (_wpnonce) is required for unauthenticated access.
  • The "authentication" is entirely handled within the userDetail function via custom HTTP headers, bypassing the standard WordPress REST authentication cookies and nonces.

5. Exploitation Strategy

The exploit will attempt to retrieve the password hash of the primary administrator (ID 1) by spoofing an admin request.

Step 1: Identify Admin Username

Use the http_request tool to check for common admin usernames if not already known.

  • Request: GET /wp-json/wp/v2/users
  • Target: Look for users with the role "administrator" or ID 1.

Step 2: Perform the Information Leak

Send the malicious request to the vulnerable endpoint.

  • Tool: http_request
  • Method: GET
  • URL: http://localhost:8080/wp-json/wp/v3/user/list/1
  • Headers:
    Username: admin
    Password: arbitrary_value
    Accept: application/json
    

Step 3: Parse the Response

The expected response is a JSON object. We will specifically look for the user_pass field.

6. Test Data Setup

To verify the exploit in the test environment:

  1. Users: Ensure at least one administrator exists with the username admin.
  2. Plugin: Install and activate wp-forms-connector version 1.8.
  3. Target: Ensure there is a user with ID 1 (standard for first admin).

7. Expected Results

A successful exploit will return an HTTP 200 OK with a JSON body similar to:

{
    "ID": "1",
    "user_login": "admin",
    "user_pass": "$P$By6E...[REDACTED]...",
    "user_email": "admin@example.com",
    "user_registered": "2023-10-27 10:00:00"
}

If the exploit fails, the response might be a 401/403 or an error message indicating invalid credentials (if the headers are missing or the username is incorrect).

8. Verification Steps

After performing the HTTP request, verify the leaked data against the actual database state using WP-CLI:

# Get the actual hash from the database
wp user get 1 --field=user_pass

# Compare the hash returned by the http_request tool with this value.

9. Alternative Approaches

  • ID Enumeration: If ID 1 is not the target, use a loop/intruder-style approach to request IDs 1 through 100 to dump the entire user database.
  • Username Discovery: If admin is not the username, try manager, webmaster, or use the wp/v2/users endpoint to find valid login names.
  • Endpoint Variation: If GET fails, attempt a POST request to the same endpoint with the same headers, as some REST handlers are permissive with methods.
Research Findings
Static analysis — not yet PoC-verified

Summary

The WP Forms Connector plugin for WordPress exposes sensitive user data, including password hashes and email addresses, via an insecure custom REST API endpoint. The vulnerability occurs because the plugin's internal authentication logic only checks if a provided 'Username' belongs to an administrator and if a 'Password' header is non-empty, without actually validating the password's correctness.

Vulnerable Code

// In rest route registration
register_rest_route( 'wp/v3', '/user/list/(?P<id>[\d]+)', array(
    'methods'             => 'GET',
    'callback'            => 'userDetail',
    'permission_callback' => '__return_true',
) );

---

// In callback function userDetail()
function userDetail( $data ) {
    $id = $data['id'];
    $username = $_SERVER['HTTP_USERNAME'];
    $password = $_SERVER['HTTP_PASSWORD'];

    $user = get_user_by( 'login', $username );
    if ( $user && in_array( 'administrator', (array) $user->roles ) ) {
        // The vulnerability: verifies password is not empty, but does not call wp_check_password()
        if ( ! empty( $password ) ) {
            return get_userdata( $id );
        }
    }
}

Security Fix

--- wp-forms-connector/wp-forms-connector.php
+++ wp-forms-connector/wp-forms-connector.php
@@ -20,1 +20,1 @@
-        'permission_callback' => '__return_true',
+        'permission_callback' => function() { return current_user_can('manage_options'); },
@@ -35,1 +35,1 @@
-        if ( ! empty( $password ) ) {
+        if ( ! empty( $password ) && wp_check_password( $password, $user->user_pass, $user->ID ) ) {

Exploit Outline

The exploit targets the '/wp-json/wp/v3/user/list/<id>' endpoint using a GET request. The attacker must provide two custom HTTP headers: 'Username', containing the login name of a valid WordPress administrator (e.g., 'admin'), and 'Password', containing any arbitrary non-empty string. Because the 'permission_callback' is set to return true and the function fails to verify the password hash using wp_check_password(), the endpoint returns the full user object for the specified ID, including the 'user_pass' hash and 'user_email'.

Check if your site is affected.

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