
Detectar com segurança se um servidor UniFi OS é vulnerável ao CVE-2026-34908.
Um detector seguro para a cadeia de execução remota de código não autenticada no UniFi OS Server ≤ 5.0.6, divulgada no Boletim de Aviso de Segurança 064 da Ubiquiti:
| CVE | Classe | Papel na cadeia |
|---|---|---|
| CVE-2026-34908 / CVE-2026-34909 | Controle de acesso inadequado / path traversal | Bypass do gateway de autenticação (a base) |
| CVE-2026-34910 | Validação inadequada de entrada → injeção de comando | RCE não autenticada alcançada através do bypass |
Corrigido no UniFi OS Server 5.0.8.
Sim. O detector foi projetado para uso em produção e avaliação:
GET simples.VULNERABLE exige tanto que o bypass de autenticação tenha alcançado o manipulador vulnerável quanto que uma requisição de base (mesmo endpoint, sem bypass) tenha sido corretamente rejeitada com 401.O UniFi OS coloca o nginx na frente de seus serviços, que impõe autenticação por meio de uma subrequisição. Essa verificação de autenticação trata qualquer requisição cuja URI crua comece com /api/auth/validate-sso/ como pública, mas o nginx roteia para o backend usando a URI normalizada (ele decodifica percentuais %2f→/ e colapsa ../). Uma requisição como:
GET /api/auth/validate-sso/..%2f..%2f..%2fproxy/users/api/v2/ucs/update/latest_package
é portanto tratada como pública (prefixo cru) mas roteada para o endpoint interno autenticado de atualização de pacotes (caminho normalizado). Sem pkg_name, esse endpoint responde query param pkg_name required — provando que o bypass funciona e o manipulador vulnerável está acessível.
O detector também envia uma requisição de base para o mesmo endpoint sem o bypass e exige que ela retorne 401 antes de declarar um host como vulnerável. A verificação testa o comportamento vulnerável diretamente — um veredito VULNERABLE significa que o bypass realmente alcançou o sink.
Sempre que a sonda não confirma positivamente VULNERABLE ou PATCHED, o detector busca a página raiz e procura pela impressão digital do portal de gerenciamento do UniFi OS (<title>UniFi OS</title>, window.UNIFI_OS_MANIFEST,id="portal-root", id="site-manager_portal-container"). Isso se aplica também a um 401: um host UniFi OS que impõe autenticação no bypass é INCONCLUSIVE, mas um proxy não-UniFi que simplesmente retorna 401 para tudo não carrega impressão digital e é reportado como UNAFFECTED. Portanto, todo resultado "não vulnerável" é fundamentado na impressão digital: marcadores presentes → INCONCLUSIVE; marcadores ausentes → UNAFFECTED (o CVE não se aplica).
# single host (default port 11443)
./cve_2026_34908_check.py 192.168.1.10
# explicit port / URL forms
./cve_2026_34908_check.py host-a:11443 https://host-b
# scan a list, one target per line ('#' comments allowed), compact output
./cve_2026_34908_check.py -f targets.txt --brief
# machine-readable output for pipelines
./cve_2026_34908_check.py -f targets.txt --json > results.json
Um console vulnerável (verboso, o padrão). A segunda linha é o detalhe do veredito; o marcador [!] e VULNERABLE são renderizados em vermelho em um TTY:
$ ./cve_2026_34908_check.py 192.168.1.10
[!] 192.168.1.10:11443: VULNERABLE
auth bypass reached the vulnerable handler (no command executed); baseline correctly 401
Um console corrigido (5.0.8+):
$ ./cve_2026_34908_check.py 192.168.1.11
[+] 192.168.1.11:11443: PATCHED
nginx rejected the normalized-path divergence (HTTP 400) — 5.0.8+ behavior
Um host UniFi OS confirmado que a sonda não pôde classificar → INCONCLUSIVE. A linha de detalhe distingue os dois casos (autenticação imposta vs. resposta inesperada):
$ ./cve_2026_34908_check.py 192.168.1.12 192.168.1.13
[?] 192.168.1.12:11443: INCONCLUSIVE
bypass blocked / auth enforced (HTTP 401) on a confirmed UniFi OS host — not confirmed vulnerable
[?] 192.168.1.13:11443: INCONCLUSIVE
UniFi OS detected, but probe returned an unexpected response: HTTP 302 text/html
Um host que não é UniFi OS → UNAFFECTED (o aviso não se aplica):
$ ./cve_2026_34908_check.py 203.0.113.9:443
[-] 203.0.113.9:443: UNAFFECTED
no UniFi OS web fingerprint on / (probe HTTP 404) — target is not a UniFi OS Server
Escaneie uma lista, uma linha alinhada por host (--brief). O código de saída é 1 se algum host for VULNERABLE, caso contrário 0 — útil em scripts:
$ ./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
Saída legível por máquina para pipelines (--json). Cada resultado carrega o verdict mais o bypass.state/bypass.detail por trás dele; resultados ERROR carregam um campo error em vez de 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"
}
]
| Código | Significado |
|---|---|
0 | Nenhum alvo retornou VULNERABLE |
1 | Pelo menos um alvo está VULNERABLE |
2 | Erro de uso (argumentos inválidos / arquivo de alvos ilegível) |
INCONCLUSIVE não é uma garantia de segurança — confirma um host UniFi OS mas não pôde classificá-lo (autenticação imposta no bypass, ou uma resposta inesperada). Um host que é fortemente filtrado ou protegido por um proxy inesperado pode não ser classificável apenas pela rede. Confirme a versão em execução quando possível.UNAFFECTED significa que a página raiz não carregou impressão digital do portal UniFi OS (incluindo hosts que retornam 401 sem ela). Um console UniFi OS escondido atrás de um proxy reverso que remove ou reescreve o HTML do portal poderia, portanto, ser reportado incorretamente; confirme diretamente se espera-se que o alvo seja UniFi OS.Atualize o UniFi OS Server para a versão 5.0.8 ou posterior. A correção adiciona uma comparação de URI crua versus normalizada no nginx (fechando o bypass de autenticação) e validação de entrada no caminho de atualização de pacotes (fechando a injeção de comando).
Este código é distribuído sob uma licença MIT.
O uso desta ferramenta para atacar alvos sem consentimento mútuo prévio é ilegal. É responsabilidade do usuário final obedecer a todas as leis locais, estaduais e federais aplicáveis. Os desenvolvedores não assumem responsabilidade e não são responsáveis por qualquer uso indevido ou dano causado por este programa.
| Resposta da sonda | Veredito |
|---|
200 + marcadores de erro do manipulador | VULNERABLE |
400 (nginx rejeita a divergência) | PATCHED (5.0.8+) |
401, impressão digital do UniFi OS presente | INCONCLUSIVE (autenticação imposta / bypass bloqueado) |
401, sem impressão digital do UniFi OS | UNAFFECTED (não é um Servidor UniFi OS) |
| qualquer outra coisa, sem impressão digital do UniFi OS | UNAFFECTED (não é um Servidor UniFi OS) |
| qualquer outra coisa, impressão digital do UniFi OS presente | INCONCLUSIVE (resposta inesperada) |
| Bandeira | Descrição |
|---|
targets | Um ou mais host, host:port, ou https://host:port |
-f, --targets-file FILE | Lê alvos de um arquivo (um por linha; comentários #) |
--brief | Uma única linha alinhada por alvo — ideal para escanear muitos hosts |
--json | Emite resultados JSON estruturados |
--timeout SECS | Timeout por requisição (padrão: 10) |
--no-color | Desativa saída colorida (também respeita NO_COLOR e não-TTY) |
| Veredito | Significado |
|---|
VULNERABLE | Bypass de autenticação alcançou o manipulador vulnerável de forma não autenticada. Atualize para 5.0.8+. |
PATCHED | nginx rejeitou a divergência de caminho normalizado (comportamento da 5.0.8+). |
UNAFFECTED | Nenhuma impressão digital do portal UniFi OS na página raiz — o alvo não é um Servidor UniFi OS, portanto o aviso não se aplica. Inclui hosts que retornam 401 sem a impressão digital (por exemplo, um proxy não relacionado que rejeita tudo). |
INCONCLUSIVE | Host UniFi OS confirmado que não pôde ser classificado — verifique a versão manualmente. A linha de detalhe do veredito indica qual caso: (a) o bypass foi bloqueado / autenticação imposta (401), ou (b) a sonda retornou uma resposta inesperada. |
ERROR | Falha de conexão/timeout/TLS. |