CVE-2026-1537

LatePoint – Calendar Booking Plugin for Appointments and Events <= 5.2.6 - Missing Authorization to Booking Details Exposure

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
5.2.7
Patched in
1d
Time to patch

Description

The LatePoint – Calendar Booking Plugin for Appointments and Events plugin for WordPress is vulnerable to unauthorized access of data due to a missing capability check on the load_step() function in all versions up to, and including, 5.2.6. This makes it possible for unauthenticated attackers to view booking information including customer names, email addresses, phone numbers, appointment times, and service details.

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<=5.2.6
PublishedFebruary 11, 2026
Last updatedFebruary 12, 2026
Affected pluginlatepoint

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-1537 - LatePoint Booking Details Exposure ## 1. Vulnerability Summary The LatePoint plugin (<= 5.2.6) contains a missing authorization vulnerability within its AJAX routing system, specifically targeting the `load_step()` function. The plugin uses a custom rou…

Show full research plan

Exploitation Research Plan: CVE-2026-1537 - LatePoint Booking Details Exposure

1. Vulnerability Summary

The LatePoint plugin (<= 5.2.6) contains a missing authorization vulnerability within its AJAX routing system, specifically targeting the load_step() function. The plugin uses a custom routing mechanism where requests are funneled through a central AJAX handler. The load_step method, intended to transition users through the booking wizard steps, fails to validate whether the requester has permission to view the details of a specific booking_id. Consequently, an unauthenticated attacker can supply a booking ID and retrieve sensitive information including customer names, email addresses, phone numbers, and appointment specifics.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Actions: latepoint_route_call (authenticated) and wp_ajax_nopriv_latepoint_route_call (unauthenticated).
  • Vulnerable Route: bookings__load_step (Inferred from LatePoint's controller__action routing convention).
  • Payload Parameter: booking_id or id passed via POST.
  • Authentication: None required (unauthenticated).
  • Preconditions: At least one booking must exist in the system for data to be exposed.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with action=latepoint_route_call.
  2. Routing: The request is handled by OsRouterHelper::route(). LatePoint parses the route parameter (e.g., bookings__load_step).
  3. Controller Dispatch: The router instantiates OsBookingsController and calls the load_step() method.
  4. Vulnerable Logic (Inferred):
    • load_step() retrieves the booking_id from the $_POST or $_GET array.
    • It fetches the booking object: $booking = new OsBookingModel($booking_id);.
    • It determines which step to display (often the "verify" or "confirmation" step).
    • The Flaw: The code lacks a check such as if ($booking->customer_id != $current_customer_id && !current_user_can('manage_options')).
  5. Data Sink: The controller renders a template (view) containing the booking details and returns it as a JSON response or raw HTML.

4. Nonce Acquisition Strategy

LatePoint typically uses a localized JavaScript object to manage its AJAX operations.

  1. Identify the Script: The plugin enqueues its core JS on pages containing the booking shortcode.
  2. Shortcode: [latepoint_book_button] or [latepoint_booking_form].
  3. Strategy:
    • Create a public page with the shortcode: wp post create --post_type=page --post_status=publish --post_title="Booking" --post_content='[latepoint_booking_form]'.
    • Navigate to this page.
    • Extract the nonce from the latepoint_helper or latepoint_wizard_vars object.
  4. JS Verification: Use browser_eval to find the nonce:
    • browser_eval("window.latepoint_helper?.latepoint_token") (Inferred identifier).
    • Note: If the plugin allows unauthenticated routing without a nonce for the wizard (common in booking plugins to avoid session expiration issues), the request may work with an empty or omitted nonce.

5. Exploitation Strategy

The goal is to request the "verify" step for a known or guessed booking ID.

  • Request Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php
  • Content-Type: application/x-www-form-urlencoded
  • Payload:
    action=latepoint_route_call&route=bookings__load_step&id=<BOOKING_ID>&step_name=verify
    
    (Note: step_name might also be contact, payment, or confirmation depending on the exact version's view names.)

Step-by-Step Plan:

  1. Setup Data: Ensure a booking exists (see Test Data Setup).
  2. Extract Nonce: (If required) Navigate to the page with the shortcode and extract the token.
  3. Perform Attack: Use http_request to call the route with an incremental id.
  4. Capture Response: Analyze the html or data field in the JSON response for PII strings (Email, Phone, Name).

6. Test Data Setup

To simulate a populated environment:

  1. Create a Customer:
    wp eval "if(!class_exists('OsCustomerModel')) { /* load plugin */ } $customer = new OsCustomerModel(); $customer->set_variables(['first_name' => 'Vulnerable', 'last_name' => 'User', 'email' => 'victim@example.com'])->save();"
  2. Create a Booking:
    wp eval "$booking = new OsBookingModel(); $booking->set_variables(['customer_id' => 1, 'service_id' => 1, 'agent_id' => 1, 'start_date' => '2026-01-01', 'start_time' => 600, 'end_time' => 660, 'status' => 'approved'])->save();"
  3. Publish Booking Page:
    wp post create --post_type=page --post_status=publish --post_title="Book" --post_content='[latepoint_booking_form]'

7. Expected Results

  • Status Code: 200 OK.
  • Response Body: A JSON object containing an html key.
  • Evidence: Inside the html string, look for:
    • <span class="value">victim@example.com</span>
    • Specific customer labels like latepoint-customer-info.
    • The booking ID and date/time.

8. Verification Steps

After the exploit attempt, verify the data matches the database:

  1. Check the booking ID used in the exploit:
    wp db query "SELECT * FROM wp_latepoint_bookings WHERE id = <ID>"
  2. Compare the output email/name with the values returned in the http_request response.

9. Alternative Approaches

  • Route Variation: If bookings__load_step is restricted, try bookings__print_order_confirmation or bookings__get_customer_details.
  • Parameter Variation: Try booking_id instead of id.
  • Direct View Access: LatePoint sometimes allows direct template loading via latepoint_get_template_part. Check if the verify step template can be loaded directly through the router.
  • ID Brute Forcing: Since booking IDs are sequential integers, script a loop to iterate from 1 to 100 to demonstrate mass exposure.
Research Findings
Static analysis — not yet PoC-verified

Summary

The LatePoint plugin for WordPress (<= 5.2.6) suffers from an insecure direct object reference (IDOR) vulnerability in its AJAX routing system. Unauthenticated attackers can supply a booking ID to the `load_step` action and retrieve sensitive booking information, including customer names, emails, and phone numbers, because the plugin fails to verify if the requester is authorized to view the specific booking.

Vulnerable Code

// lib/controllers/bookings_controller.php

public function load_step() {
  $booking_id = $this->get_param('id');
  $booking = new OsBookingModel($booking_id);

  // Vulnerability: No authorization check to ensure the current user 
  // is either an admin or the owner of the booking.
  $this->vars['booking'] = $booking;
  $this->format_render(__FUNCTION__);
}

Security Fix

--- a/lib/controllers/bookings_controller.php
+++ b/lib/controllers/bookings_controller.php
@@ -102,6 +102,11 @@
   public function load_step() {
     $booking_id = $this->get_param('id');
     $booking = new OsBookingModel($booking_id);
+
+    if (!OsAuthHelper::is_admin_logged_in() && !OsAuthHelper::is_current_customer($booking->customer_id)) {
+      wp_send_json_error(['message' => 'Unauthorized']);
+      return;
+    }
+
     $this->vars['booking'] = $booking;
     $this->format_render(__FUNCTION__);
   }

Exploit Outline

1. Identify a WordPress site running LatePoint <= 5.2.6. 2. Locate the AJAX endpoint at `/wp-admin/admin-ajax.php`. 3. Identify the required action (usually `latepoint_route_call`) and potentially extract a nonce from the source of a page containing a booking shortcode (e.g., `latepoint_helper.latepoint_token`). 4. Craft a POST request to the AJAX endpoint with the following parameters: `action=latepoint_route_call`, `route=bookings__load_step`, `id=[TARGET_BOOKING_ID]`, and `step_name=verify` (or `confirmation`). 5. Submit the request unauthenticated. Since booking IDs are typically sequential integers, an attacker can iterate through IDs to scrape data. 6. The server response will contain a JSON object with an `html` field containing the rendered template for the requested step, which includes PII such as customer names, email addresses, and phone numbers.

Check if your site is affected.

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