
Безопасно определить, уязвим ли сервер 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 — это доказывает, что обход работает и уязвимый обработчик достижим.
Детектор также отправляет базовый запрос на тот же 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
Уязвимая консоль (подробный, по умолчанию). Вторая строка — детали вердикта; маркер [!] и 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"
}
]
| Код | Значение |
|---|---|
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.
Использование этого инструмента для атаки на цели без предварительного взаимного согласия незаконно. Ответственность за соблюдение всех применимых местных, государственных и федеральных законов лежит на конечном пользователе. Разработчики не несут ответственности и не отвечают за любое неправомерное использование или ущерб, причиненный этой программой.
| Ответ зонда | Вердикт |
|---|
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 (неожиданный ответ) |
| Флаг | Описание |
|---|
targets | Один или несколько host, host:port или https://host:port |
-f, --targets-file FILE | Читать цели из файла (одна в строке; комментарии #) |
--brief | Одна выровненная строка на цель — идеально для сканирования множества хостов |
--json | Выводить структурированные результаты JSON |
--timeout SECS | Таймаут на запрос (по умолчанию: 10) |
--no-color | Отключить цветной вывод (также учитывает NO_COLOR и не-TTY) |
| Вердикт | Значение |
|---|
VULNERABLE | Обход аутентификации достиг уязвимого обработчика без аутентификации. Обновите до 5.0.8+. |
PATCHED | nginx отклонил расхождение нормализованного пути (поведение 5.0.8+). |
UNAFFECTED | Отпечаток портала UniFi OS на корневой странице отсутствует — цель не является сервером UniFi OS, поэтому уведомление не применяется. Включает хосты, возвращающие 401 без отпечатка (например, посторонний прокси, отклоняющий всё). |
INCONCLUSIVE | Подтвержденный хост UniFi OS, который не удалось классифицировать — проверьте версию вручную. Строка деталей вердикта указывает на случай: (a) обход заблокирован / аутентификация включена (401), или (b) зонд вернул неожиданный ответ. |
ERROR | Ошибка соединения/таймаута/TLS. |