
Безопасно определить, уязвим ли сервер UniFi OS для CVE-2026-34908
Безопасный детектор для цепочки удаленного выполнения кода без аутентификации в 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→/ и схлопывает ../). Запрос вида:
GET /api/auth/validate-sso/..%2f..%2f..%2fproxy/users/api/v2/ucs/update/latest_package
таким образом, считается публичным (сырой префикс), но маршрутизируется к аутентифицированному внутреннему endpoint для обновления пакетов (нормализованный путь). Без pkg_name этот endpoint отвечает query param pkg_name required — это доказывает, что обход работает и уязвимый обработчик достижим.
| Ответ зонда | Вердикт |
|---|---|
200 + маркеры ошибок обработчика | VULNERABLE |
400 (nginx отклоняет расхождение) | PATCHED (5.0.8+) |
401, отпечаток UniFi OS присутствует | INCONCLUSIVE (аутентификация включена / обход заблокирован) |
401, отпечатка UniFi OS нет | UNAFFECTED (не является сервером UniFi OS) |
| что-то ещё, отпечатка UniFi OS нет | UNAFFECTED (не является сервером UniFi OS) |
| что-то ещё, отпечаток UniFi OS присутствует | INCONCLUSIVE (неожиданный ответ) |
Детектор также отправляет базовый запрос на тот же endpoint без обхода и требует, чтобы он вернул 401, прежде чем объявить хост уязвимым. Проверка тестирует уязвимое поведение напрямую — вердикт VULNERABLE означает, что обход действительно достиг стока.
Когда зонд не подтверждает положительно 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 не применима).
# один хост (порт по умолчанию 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
| Флаг | Описание |
|---|---|
targets | Один или несколько host, host:port или https://host:port |
-f, --targets-file FILE | Читать цели из файла (одна в строке; комментарии #) |
--brief | Одна выровненная строка на цель — идеально для сканирования множества хостов |
--json | Выводить структурированные результаты JSON |
--timeout SECS | Таймаут на запрос (по умолчанию: 10) |
--no-color | Отключить цветной вывод (также учитывает NO_COLOR и не-TTY) |
Уязвимая консоль (подробный, по умолчанию). Вторая строка — детали вердикта; маркер [!] и VULNERABLE отображаются красным на TTY:
$ ./cve_2026_34908_check.py 192.168.1.10
[!] 192.168.1.10:11443: VULNERABLE
обход аутентификации достиг уязвимого обработчика (команда не выполнялась); базовый запрос корректно вернул 401
Запатченная консоль (5.0.8+):
$ ./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. неожиданный ответ):
$ ./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 (уведомление не применяется):
$ ./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 — удобно в скриптах:
$ ./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:
$ ./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"
}
]