## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-BISHOPFOX-CVE-2026-34908-CHECK
# Скрипт обнаружения цепочки RCE без аутентификации на UniFi OS Server
Безопасный детектор для цепочки удаленного выполнения кода без аутентификации в UniFi OS Server ≤ 5.0.6, раскрытой в Security Advisory Bulletin 064 от Ubiquiti:
CVE| Класс| Роль в цепочке
---|---|---
CVE-2026-34908 / CVE-2026-34909| Некорректный контроль доступа / обход пути| Обход шлюза аутентификации (плацдарм)
CVE-2026-34910| Некорректная проверка ввода → внедрение команд| Удаленное выполнение кода без аутентификации через обход
Исправлено в UniFi OS Server 5.0.8.
## Безопасно ли запускать?
Да. Детектор разработан для использования в производстве и оценке:
* **Ни одна команда не выполняется.** Зонд достигает уязвимой конечной точки без обязательного параметра, поэтому обработчик отклоняет отсутствующий ввод, и мы подтверждаем ошибку по этой ошибке валидации.
* **Состояние цели не изменяется.** Каждый запрос — обычный `GET`.
* **Защита от ложных срабатываний.** Вердикт `VULNERABLE` требует, чтобы обход аутентификации достиг уязвимого обработчика, и чтобы базовый запрос (тот же конечный пункт, без обхода) был корректно отклонен с кодом `401`.
## Как это работает
UniFi OS размещает свои службы через nginx, который обеспечивает аутентификацию с помощью подзапроса. Эта проверка аутентификации считает любой запрос, чей **сырой** URI начинается с `/api/auth/validate-sso/`, публичным, но nginx маршрутизирует на бэкенд, используя **нормализованный** URI (он декодирует процент `%2f`→`/` и схлопывает `../`). Запрос вида:
root@kitploit:~
GET /api/auth/validate-sso/..%2f..%2f..%2fproxy/users/api/v2/ucs/update/latest_package
таким образом, считается публичным (сырой префикс), но маршрутизируется к аутентифицированному внутреннему endpoint для обновления пакетов (нормализованный путь). Без `pkg_name` этот endpoint отвечает `query param pkg_name required` — это доказывает, что обход работает и уязвимый обработчик достижим.
Детектор также отправляет базовый запрос на тот же endpoint без обхода и требует, чтобы он вернул `401`, прежде чем объявить хост уязвимым. Проверка тестирует уязвимое поведение напрямую — вердикт `VULNERABLE` означает, что обход действительно достиг стока.
### Подтверждение, что цель является UniFi OS, прежде чем вынести вердикт об отсутствии уязвимости
Когда зонд не подтверждает положительно `VULNERABLE` или `PATCHED`, детектор запрашивает корневую страницу и ищет отпечаток портала управления UniFi OS ( `<title>UniFi OS</title>`, `window.UNIFI_OS_MANIFEST`,`id="portal-root"`, `id="site-manager_portal-container"`). Это относится и к `401`: хост UniFi OS, который применяет аутентификацию к обходу, получает `INCONCLUSIVE`, но не-UniFi прокси, который просто отдает `401` на всё, не несет отпечатка и сообщается как `UNAFFECTED`. Таким образом, каждый исход "не уязвим" обоснован отпечатком: маркеры присутствуют → `INCONCLUSIVE`; маркеры отсутствуют → `UNAFFECTED` (CVE не применима).
## Требования
* Python 3.7+, только стандартная библиотека — сторонних пакетов не требуется.
## Использование
root@kitploit:~
# один хост (порт по умолчанию 11443)
./cve_2026_34908_check.py 192.168.1.10
# явное указание порта / URL
./cve_2026_34908_check.py host-a:11443 https://host-b
# сканирование списка, одна цель в строке (допускаются комментарии '#'), компактный вывод
./cve_2026_34908_check.py -f targets.txt --brief
# машиночитаемый вывод для конвейеров
./cve_2026_34908_check.py -f targets.txt --json > results.json
### Параметры
### Примеры
**Уязвимая консоль** (подробный, по умолчанию). Вторая строка — детали вердикта; маркер `[!]` и `VULNERABLE` отображаются красным на TTY:
root@kitploit:~
$ ./cve_2026_34908_check.py 192.168.1.10
[!] 192.168.1.10:11443: VULNERABLE
обход аутентификации достиг уязвимого обработчика (команда не выполнялась); базовый запрос корректно вернул 401
**Запатченная консоль** (5.0.8+):
root@kitploit:~
$ ./cve_2026_34908_check.py 192.168.1.11
[+] 192.168.1.11:11443: PATCHED
nginx отклонил расхождение нормализованного пути (HTTP 400) — поведение 5.0.8+
**Подтвержденный хост UniFi OS, который зонд не смог классифицировать** → `INCONCLUSIVE`. Строка деталей различает два случая (аутентификация включена vs. неожиданный ответ):
root@kitploit:~
$ ./cve_2026_34908_check.py 192.168.1.12 192.168.1.13
[?] 192.168.1.12:11443: INCONCLUSIVE
обход заблокирован / аутентификация включена (HTTP 401) на подтвержденном хосте UniFi OS — не подтверждена уязвимость
[?] 192.168.1.13:11443: INCONCLUSIVE
UniFi OS обнаружен, но зонд вернул неожиданный ответ: HTTP 302 text/html
**Хост, который вообще не является UniFi OS** → `UNAFFECTED` (уведомление не применяется):
root@kitploit:~
$ ./cve_2026_34908_check.py 203.0.113.9:443
[-] 203.0.113.9:443: UNAFFECTED
отпечатка веб-портала UniFi OS на / нет (зонд HTTP 404) — цель не является сервером UniFi OS
**Сканирование списка, одна выровненная строка на хост** (`--brief`). Код завершения `1`, если любой хост `VULNERABLE`, иначе `0` — удобно в скриптах:
root@kitploit:~
$ ./cve_2026_34908_check.py -f targets.txt --brief; echo "exit: $?"
VULNERABLE 192.168.1.10:11443
PATCHED 192.168.1.11:11443
INCONCLUSIVE 192.168.1.12:11443
UNAFFECTED 203.0.113.9:443
ERROR 10.0.0.1:11443 timeout
exit: 1
**Машиночитаемый вывод для конвейеров** (`--json`). Каждый результат содержит `verdict` плюс `bypass.state`/`bypass.detail`; результаты `ERROR` содержат поле `error` вместо `bypass`:
root@kitploit:~
$ ./cve_2026_34908_check.py 192.168.1.10 192.168.1.11 10.0.0.1 --json
[
{
"target": "192.168.1.10:11443",
"bypass": {
"state": "vulnerable",
"detail": "auth bypass reached the vulnerable handler (no command executed); baseline correctly 401"
},
"verdict": "VULNERABLE"
},
{
"target": "192.168.1.11:11443",
"bypass": {
"state": "patched",
"detail": "nginx rejected the normalized-path divergence (HTTP 400) — 5.0.8+ behavior"
},
"verdict": "PATCHED"
},
{
"target": "10.0.0.1:11443",
"verdict": "ERROR",
"error": "timeout"
}
]
## Вердикты
## Коды завершения
Код| Значение
---|---
`0`| Ни одна цель не вернула `VULNERABLE`
`1`| Хотя бы одна цель `VULNERABLE`
`2`| Ошибка использования (неверные аргументы / нечитаемый файл целей)
## Ограничения
* `INCONCLUSIVE` не является гарантией безопасности — он подтверждает хост UniFi OS, но не смог его классифицировать (аутентификация включена на обходе или неожиданный ответ). Хост, сильно фильтруемый или находящийся за неожиданным прокси, может не классифицироваться только по сети. По возможности подтвердите запущенную версию.
* `UNAFFECTED` означает, что корневая страница не содержит отпечатка портала UniFi OS (включая хосты, которые отдают `401` без него). Консоль UniFi OS, скрытая за обратным прокси, который удаляет или перезаписывает HTML портала, может быть ошибочно сообщена; подтвердите напрямую, если ожидается, что цель является UniFi OS.
* Детектор сообщает о достижимости уязвимого поведения.
## Устранение
Обновите сервер UniFi OS до версии 5.0.8 или новее. Исправление добавляет сравнение сырого и нормализованного URI в nginx (закрывая обход аутентификации) и проверку ввода в пути обновления пакетов (закрывая внедрение команд).
## Лицензия
Этот код распространяется по лицензии MIT.
## Правовое предупреждение
Использование этого инструмента для атаки на цели без предварительного взаимного согласия незаконно. Ответственность за соблюдение всех применимых местных, государственных и федеральных законов лежит на конечном пользователе. Разработчики не несут ответственности и не отвечают за любое неправомерное использование или ущерб, причиненный этой программой.
## См. также
* Ubiquiti Security Advisory Bulletin 064
* Bishop Fox Blog: Full Technical Analysis