CVE-2026-1980

WPBookit <= 1.0.8 - Missing Authorization to Unauthenticated Sensitive Customer Data Exposure

mediumExposure of Sensitive Information to an Unauthorized Actor
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.0.9
Patched in
1d
Time to patch

Description

The WPBookit plugin for WordPress is vulnerable to unauthorized data disclosure due to a missing authorization check on the 'get_customer_list' route in all versions up to, and including, 1.0.8. This makes it possible for unauthenticated attackers to retrieve sensitive customer information including names, emails, phone numbers, dates of birth, and gender.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.0.8
PublishedMarch 3, 2026
Last updatedMarch 4, 2026
Affected pluginwpbookit

What Changed in the Fix

Changes introduced in v1.0.9

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-1980 (WPBookit <= 1.0.8) ## 1. Vulnerability Summary The **WPBookit** plugin for WordPress is vulnerable to **Missing Authorization** in its internal AJAX routing system. Specifically, the route `get_customer_list` lacks any permission or nonce checks. Because…

Show full research plan

Exploitation Research Plan: CVE-2026-1980 (WPBookit <= 1.0.8)

1. Vulnerability Summary

The WPBookit plugin for WordPress is vulnerable to Missing Authorization in its internal AJAX routing system. Specifically, the route get_customer_list lacks any permission or nonce checks. Because the plugin registers both authenticated (wp_ajax_) and unauthenticated (wp_ajax_nopriv_) hooks for its central routing handler, any user (including unauthenticated visitors) can invoke the get_customer_list action. This results in the exposure of sensitive customer data, including full names, email addresses, phone numbers, dates of birth, and gender.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wpb_ajax_get (registered via wp_ajax_nopriv_wpb_ajax_get)
  • Route Name: get_customer_list
  • Method: GET (or POST since $_REQUEST is used in the handler)
  • Authentication: Unauthenticated (No login required)
  • Preconditions: At least one customer or guest must be registered in the system for the data to be returned.

3. Code Flow

  1. Entry Point: In core/admin/classes/class.wpb-admin-routes-handler.php, the event_Handler() function registers:
    add_action( "wp_ajax_wpb_ajax_get", [ $this, 'wpb_ajax_get' ] );
    add_action( "wp_ajax_nopriv_wpb_ajax_get", [ $this, 'wpb_ajax_get' ] );
    
  2. Routing Logic: When wpb_ajax_get is called, it identifies the route from the route_name parameter:
    $route_name = isset($_REQUEST['route_name']) ? sanitize_text_field(wp_unslash($_REQUEST['route_name'])) : '';
    
  3. Permission Check Failure: The handler only enforces permissions if a permission key is defined for the route in the route configuration:
    if (isset($route['permission']) && !empty($route['permission'])) {
        if (!is_user_logged_in() || !current_user_can($route['permission'])) {
            // Error thrown
        }
    }
    
  4. Target Route: In core/admin/classes/class.wpb-admin-routes.php, the get_customer_list route is defined without a permission or nonce key:
    'get_customer_list'    => [
        'method' => 'get',
        'action' => 'WPBOOKIT_Customer_Controller@get_customer_list',
        'module' => 'customer-controller',
        'dependency' => array(...)
    ],
    
  5. Sink: The call($route) method is invoked, which executes WPBOOKIT_Customer_Controller::get_customer_list(), returning the customer database to the requester.

4. Nonce Acquisition Strategy

According to the code in core/admin/classes/class.wpb-admin-routes-handler.php, no nonce is required for GET requests handled by wpb_ajax_get.

  • The wpb_ajax_post method checks if ($route['nonce'] === 1).
  • The wpb_ajax_get method omits this block entirely.
  • The get_customer_list route in class.wpb-admin-routes.php does not define a nonce key regardless.

Conclusion: No nonce acquisition is necessary for this exploit.

5. Exploitation Strategy

The exploit involves a single HTTP GET request to the AJAX endpoint.

Step 1: Request Sensitive Data

Send a GET request to retrieve the customer list. We include DataTable parameters (draw, start, length) because the backend controller (implied by Customer.js) likely expects them for pagination.

Request:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php?action=wpb_ajax_get&route_name=get_customer_list&draw=1&start=0&length=10
  • Method: GET
  • Headers: None required.

Expected Payload (in response JSON):
The response should be a JSON object containing a data array. Each object in data will contain fields such as:

  • id
  • name
  • email
  • phone
  • dob (Date of Birth)
  • gender
  • profile_img

6. Test Data Setup

To ensure the exploit returns data, at least one customer must exist in the database. Since unauthenticated users cannot usually register customers, we must set them up as an administrator first.

  1. Login as Admin.
  2. Navigate to WPBookit > Customers.
  3. Create a test customer with specific data:
    • First Name: John
    • Last Name: Doe
    • Email: johndoe@example.com
    • Phone: 1234567890
    • DOB: 1990-01-01
    • Gender: Male
  4. Alternatively, use WP-CLI to insert a record into the likely customer table (usually wp_wpb_customers or similar, check wp db tables).

7. Expected Results

  • Success: The HTTP response status is 200 OK. The body is a JSON object with data containing the customer johndoe@example.com and his PII.
  • Failure: The HTTP response status is 403 Forbidden or 401 Unauthorized, or the data array is empty (if no customers were created).

8. Verification Steps

After performing the HTTP request:

  1. Verify the JSON structure matches the columns expected in core/admin/assets/src/module/Customer.js.
  2. Use WP-CLI to confirm the data retrieved matches the database:
    wp db query "SELECT * FROM wp_wpb_customers;"
    
    (Note: verify exact table name using wp db tables | grep wpb)

9. Alternative Approaches

If get_customer_list is restricted for some reason (e.g., a silent patch), try other routes defined in class.wpb-admin-routes.php that also lack permission checks:

  • Guest List: route_name=get_guest_list
  • Booking List: route_name=booking_list (Note: this route has nonce => 1 in config, but wpb_ajax_get might still ignore it due to the missing check in the handler).
  • Booking Types: route_name=get_booking_type (May reveal business-internal service details).
Research Findings
Static analysis — not yet PoC-verified

Summary

The WPBookit plugin for WordPress (versions 1.0.8 and earlier) exposes sensitive customer data because its central AJAX routing system lacks authorization and nonce checks for the 'get_customer_list' route. This allows unauthenticated attackers to retrieve a database of customer information, including full names, email addresses, phone numbers, dates of birth, and gender.

Vulnerable Code

// core/admin/classes/class.wpb-admin-routes-handler.php:21
public function event_Handler() {
    add_action( "wp_ajax_wpb_ajax_post", [ $this, 'wpb_ajax_post' ] );
    add_action( "wp_ajax_nopriv_wpb_ajax_post", [ $this, 'wpb_ajax_post' ] );

    add_action( "wp_ajax_wpb_ajax_get", [ $this, 'wpb_ajax_get' ] );
    add_action( "wp_ajax_nopriv_wpb_ajax_get", [ $this, 'wpb_ajax_get' ] );
}

---

// core/admin/classes/class.wpb-admin-routes-handler.php:151
// Handler only enforces permissions if a 'permission' key is defined for the route
if (isset($route['permission']) && !empty($route['permission'])) {
    if (!is_user_logged_in() || !current_user_can($route['permission'])) {
        $error = __('You do not have permission to perform this action.', 'wpbookit');
        throw new Exception($error, 403);
    }
}

---

// core/admin/classes/class.wpb-admin-routes.php:143
'get_customer_list'    => [
    'method' => 'get',
    'action' => 'WPBOOKIT_Customer_Controller@get_customer_list',
    'module' => 'customer-controller',
    'dependency' => array(
        IQWPB_PLUGIN_PATH . "core/includes/wpb-core-functions.php",
        IQWPB_PLUGIN_PATH . "core/admin/classes/settings/class.wpb-settings-page.php",
        IQWPB_PLUGIN_PATH . "core/admin/classes/settings/class.wpb-settings-customer.php",
    )
],

Security Fix

--- /core/admin/classes/class.wpb-admin-routes.php
+++ /core/admin/classes/class.wpb-admin-routes.php
@@ -147,6 +147,7 @@
                 'get_customer_list'    => [
                     'method' => 'get',
                     'action' => 'WPBOOKIT_Customer_Controller@get_customer_list',
+                    'permission' => 'manage_options',
                     'module' => 'customer-controller',
                     'dependency' => array(
                         IQWPB_PLUGIN_PATH . "core/includes/wpb-core-functions.php",

Exploit Outline

The exploit is achieved by sending a single unauthenticated HTTP GET request to the WordPress AJAX endpoint. 1. Target the endpoint: /wp-admin/admin-ajax.php 2. Set the 'action' parameter to 'wpb_ajax_get' (which triggers the vulnerable nopriv handler). 3. Set the 'route_name' parameter to 'get_customer_list' (which lacks any 'permission' or 'nonce' definition in the plugin's route configuration). 4. Include standard DataTable parameters (e.g., 'draw=1', 'start=0', 'length=10') to ensure the backend controller processes the request and returns the paginated data. 5. The server will respond with a 200 OK and a JSON object containing a 'data' array populated with customer PII (names, emails, phones, DOBs).

Check if your site is affected.

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