
PoC-эксплойт для Snipe-IT (CVE-2025-59712 и CVE-2025-59713)
Этот PoC предоставляет автоматизированный скрипт для эксплуатации CVE-2025-59712 (XSS в заголовке User-Agent) и CVE-2025-59713 (небезопасная десериализация).
Эти две уязвимости были обнаружены компанией Synacktiv в ходе исследования безопасности программного обеспечения Snipe-IT. Snipe-IT — это система управления активами с открытым исходным кодом, основанная на Laravel и предназначенная для помощи организациям в отслеживании и управлении их физическими и цифровыми активами.
Техническое описание можно найти в соответствующем бюллетене безопасности на сайте Synacktiv.
Этот скрипт предоставляет три подкоманды, соответствующие режимам эксплуатации: xss, rce и fullchain.
Эта подкоманда эксплуатирует CVE-2025-59712, которая позволяет пользователю с низкими привилегиями внедрять произвольный JavaScript в HTML-страницу, отображаемую при обращении к маршруту /reports/activity. Это может сделать только администратор или пользователь, имеющий явные права на просмотр отчётов. Внедрение возможно из-за некорректной санитизации поля User-Agent, когда пользователь обновляет информацию своего профиля.
Для этого скрипт сначала войдёт в систему под учётной записью пользователя с низкими привилегиями, а затем внедрит JavaScript-код, определённый в файле, указанном через флаг --javascript.
$ python3 exploit.py xss --help
Usage: exploit.py xss [OPTIONS]
Execute XSS attack only with custom JavaScript payload
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --url -u TEXT Target Snipe-IT URL [required] │
│ * --login -l TEXT Low-privileged username [required] │
│ * --password -p TEXT Low-privileged password [required] │
│ * --new-name -n TEXT New name for low-privileged user [required] │
│ * --javascript -js TEXT Path to custom JavaScript file [required] │
│ --proxy -x TEXT HTTP proxy (http://ip:port) │
│ --verbose -v [quiet|normal|verbose] Logging verbosity [default: normal] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
[!IMPORTANT]
В ходе исследования безопасности тесты проводились на версии Snipe-IT, которая по умолчанию отображала полеUser-Agent, в которое внедряется вредоносный JavaScript. Начиная с коммита 10e5d88, свойствоUser-Agentпо умолчанию не отображается при рендеринге таблицы журнала действий. Поэтому для версий Snipe-IT после этого коммита администратор, который запустит XSS, должен установить флажокUser-Agentв параметрах представления.
Эта подкоманда эксплуатирует CVE-2025-59713, которая позволяет выполнять удалённый код при наличии учётных данных администратора или суперадминистратора. Для этого выполняются следующие шаги:
db-dumps/mysql-snipeit.sql, которые создают новое пользовательское поле и изменяют последнюю запись журнала действий на JSON-объект, содержащий Laravel pop chain, при восстановлении.[!TIP] По умолчанию Snipe-IT включает файл
.envв резервную копию. Если скрипт обнаружит его, значениеAPP_KEYбудет отображено, а файл.envбудет сохранён в каталог./output(для этого файла можно указать собственное расположение с помощью--output-dir).
[!CAUTION] Восстановление резервной копии отключает всех пользователей, подключённых к экземпляру.
/api/v1/reports/activity, который запускает десериализацию и выполняет Laravel pop chain.$ python3 exploit.py rce --help
Usage: exploit.py rce [OPTIONS]
Execute RCE attack only (requires existing admin account)
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --url -u TEXT Target Snipe-IT URL [required] │
│ * --admin-user -au TEXT Admin username [required] │
│ * --admin-pass -ap TEXT Admin password [required] │
│ --output-dir -od PATH Output dir for .env file [default: /home/ninja/Téléchargements/snipe-it-advisory/exploit/output] │
│ --shell-ip -si TEXT Reverse shell IP address │
│ --shell-port -sp INTEGER Reverse shell port │
│ --command -c TEXT Custom command (overrides reverse shell) │
│ --proxy -x TEXT HTTP proxy (http://ip:port) │
│ --verbose -v [quiet|normal|verbose] Logging verbosity [default: normal] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Подкоманда fullchain направлена на объединение обеих уязвимостей XSS и RCE. Она соответствует сценарию, в котором у вас есть доступ только к пользователю с низкими привилегиями, и вы хотите добиться выполнения удалённого кода. Это сработает только в том случае, если пользователь, посещающий страницу /reports/activity, является администратором или суперадминистратором. Действительно, только эти роли имеют права на создание и восстановление резервной копии, что необходимо для отравления базы данных и последующего запуска Laravel pop chain.
Для этого скрипт:
--command, как и в режиме RCE).User-Agent тег <scr>, чтобы заставить браузер жертвы загрузить вредоносный JavaScript-шаблон./reports/activity, срабатывает XSS, и вредоносный JavaScript загружается и выполняется браузером жертвы. С этого момента выполняются те же шаги, что и в модуле RCE, но на JavaScript.Этот режим использует несколько дополнительных JavaScript-библиотек, все права принадлежат их авторам:
$ python3 exploit.py fullchain --help
Usage: exploit.py fullchain [OPTIONS]
Execute full attack chain: XSS -> Backup manipulation -> RCE
╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ * --url -u TEXT Target Snipe-IT URL [required] │
│ * --login -l TEXT Low-privileged user's username [required] │
│ * --password -p TEXT Low-privileged user's password [required] │
│ * --new-name -n TEXT New name for low-privileged user [required] │
│ --ip -i TEXT HTTP server IP address (default: auto-detect) │
│ * --port -P INTEGER HTTP server port [required] │
│ --admin-user -au TEXT Admin username to create [default: admin_rce] │
│ --admin-pass -ap TEXT Admin password to create [default: password123] │
│ --shell-ip -si TEXT Reverse shell IP address │
│ --shell-port -sp INTEGER Reverse shell port │
│ --command -c TEXT Custom command (overrides reverse shell) │
│ --proxy -x TEXT HTTP proxy (http://ip:port) │
│ --verbose -v [quiet|normal|verbose] Logging verbosity [default: normal] │
│ --help Show this message and exit. │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Чтобы запустить этот скрипт, выполните следующие команды:
$ git clone https://github.com/synacktiv/CVE-2025-59712_CVE-2025-59713
$ cd CVE-2025-59712_CVE-2025-59713
$ python3 -m venv .venv && source .venv/bin/activate
$ python3 -m pip install -r requirements.txt
Также предоставляется Dockerfile, позволяющий опробовать скрипт и воспроизвести эксплуатацию уязвимостей. Он загружает уязвимую версию Snipe-IT, настраивает базу данных с помощью php artisan и создаёт двух пользователей:
admin с паролем по умолчанию AdminPassword123!lowpriv с паролем по умолчанию LowPrivUser123!Перед запуском контейнера необходимо обновить файлы .env и snipe-it.conf, указав URL экземпляра Snipe-IT:
$ sed -i 's|^APP_URL=.*|APP_URL=http://<IP>:<PORT>|' .env
$ sed -i 's|\(ServerName\s*\).*|\1http://<IP>:<PORT>|' snipe-it.conf
Затем можно запустить контейнер:
$ docker build . -t "snipe-it-cve"
$ docker run -p 80:80 --name "snipe-it-debian" snipe-it-cve:latest