
Détecter en toute sécurité si un UniFi OS Server est vulnérable à CVE-2026-34908
Un détecteur sûr pour la chaîne d'exécution de code à distance non authentifiée sur UniFi OS Server ≤ 5.0.6, divulguée dans le Bulletin d'avis de sécurité 064 d'Ubiquiti :
| CVE | Classe | Rôle dans la chaîne |
|---|---|---|
| CVE-2026-34908 / CVE-2026-34909 | Contrôle d'accès inapproprié / traversée de chemin | Contournement de la passerelle d'authentification (point d'appui) |
| CVE-2026-34910 | Validation d'entrée inappropriée → injection de commandes | RCE non authentifiée atteinte via le contournement |
Corrigé dans UniFi OS Server 5.0.8.
Oui. Le détecteur est conçu pour une utilisation en production et en évaluation :
GET.VULNÉRABLE nécessite à la fois que le contournement d'authentification ait
atteint le gestionnaire vulnérable et qu'une requête de base (même point d'accès, sans contournement) ait été correctement
rejetée avec 401.UniFi OS fait face à ses services avec nginx, qui applique l'authentification via une sous-requête. Cette
vérification d'authentification traite toute requête dont l'URI brute commence par /api/auth/validate-sso/ comme publique,
mais nginx route vers le backend en utilisant l'URI normalisée (il décode les pourcentages %2f→/ et
supprime ../). Une requête comme :
GET /api/auth/validate-sso/..%2f..%2f..%2fproxy/users/api/v2/ucs/update/latest_package
est donc traitée comme publique (préfixe brut) mais routée vers le point d'accès interne authentifié
de mise à jour de paquet (chemin normalisé). Sans pkg_name, ce point d'accès répond
query param pkg_name required — prouvant que le contournement fonctionne et que le gestionnaire vulnérable est
atteignable.
Le détecteur envoie également une requête de base au même point d'accès sans le contournement et
exige qu'elle renvoie 401 avant de déclarer un hôte vulnérable. Le test vérifie directement le
comportement vulnérable — un verdict VULNÉRABLE signifie que le contournement a effectivement atteint la cible.
Lorsque la sonde ne confirme pas positivement VULNÉRABLE ou CORRIGÉ, le détecteur récupère
la page racine et recherche l'empreinte du portail de gestion UniFi OS (
<title>UniFi OS</title>, window.UNIFI_OS_MANIFEST,id="portal-root",
id="site-manager_portal-container"). Cela s'applique également à un 401 : un hôte UniFi OS qui
applique l'authentification sur le contournement est NON CONCLUSIF, mais un proxy non-UniFi qui renvoie simplement 401 sur
tout ne porte aucune empreinte et est signalé NON CONCERNÉ. Ainsi, chaque résultat « non vulnérable »
est fondé sur l'empreinte : marqueurs présents → NON CONCLUSIF ; marqueurs
absents → NON CONCERNÉ (la CVE ne s'applique pas).
# 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
Une console vulnérable (mode verbeux, par défaut). La deuxième ligne est le détail du verdict ;
le marqueur [!] et VULNÉRABLE s'affichent en rouge sur un 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
Une console corrigée (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
Un hôte UniFi OS confirmé que la sonde n'a pas pu classer → INCONCLUSIVE. La ligne de détail
distingue les deux cas (authentification appliquée vs réponse inattendue) :
$ ./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
Un hôte qui n'est pas du tout UniFi OS → UNAFFECTED (l'avis ne s'applique pas) :
$ ./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
Scanner une liste, une ligne alignée par hôte (--brief). Le code de sortie est 1 si un hôte
est VULNÉRABLE, sinon 0 — pratique dans les 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
Sortie exploitable par machine pour les pipelines (--json). Chaque résultat porte le
verdict plus le bypass.state/bypass.detail sous-jacent ; les résultats ERROR portent un
champ error au lieu 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"
}
]
| Code | Signification |
|---|---|
0 | Aucune cible n'a retourné VULNÉRABLE |
1 | Au moins une cible est VULNÉRABLE |
2 | Erreur d'utilisation (mauvais arguments / fichier de cibles illisible) |
NON CONCLUSIF n'est pas une garantie de sécurité — cela confirme un hôte UniFi OS mais n'a pas pu le classer
(authentification appliquée sur le contournement, ou réponse inattendue). Un hôte fortement filtré ou
précédé d'un proxy inattendu peut ne pas être classable depuis le seul réseau. Confirmer la
version en cours d'exécution lorsque c'est possible.NON CONCERNÉ signifie que la page racine ne portait aucune empreinte du portail UniFi OS (y compris les hôtes qui
renvoient 401 sans elle). Une console UniFi OS cachée derrière un proxy inverse qui supprime ou réécrit le
HTML du portail pourrait donc être mal signalée ; confirmer directement si la cible est censée être
UniFi OS.Mettre à jour UniFi OS Server vers la version 5.0.8 ou ultérieure. Le correctif ajoute une comparaison URI brute vs normalisée dans nginx (fermant le contournement d'authentification) et une validation d'entrée dans le chemin de mise à jour du paquet (fermant l'injection de commandes).
Ce code est distribué sous une licence MIT.
L'utilisation de cet outil pour attaquer des cibles sans consentement mutuel préalable est illégale. Il est de la responsabilité de l'utilisateur final de respecter toutes les lois applicables locales, étatiques et fédérales. Les développeurs n'assument aucune responsabilité et ne sont pas responsables de tout usage abusif ou dommage causé par ce programme.
| Réponse de la sonde | Verdict |
|---|
200 + marqueurs d'erreur du gestionnaire | VULNÉRABLE |
400 (nginx rejette la divergence) | CORRIGÉ (5.0.8+) |
401, empreinte UniFi OS présente | NON CONCLUSIF (authentification appliquée / contournement bloqué) |
401, aucune empreinte UniFi OS | NON CONCERNÉ (pas un serveur UniFi OS) |
| autre chose, aucune empreinte UniFi OS | NON CONCERNÉ (pas un serveur UniFi OS) |
| autre chose, empreinte UniFi OS présente | NON CONCLUSIF (réponse inattendue) |
| Option | Description |
|---|
targets | Un ou plusieurs hôte, hôte:port, ou https://hôte:port |
-f, --targets-file FICHIER | Lire les cibles depuis un fichier (une par ligne ; commentaires #) |
--brief | Une seule ligne alignée par cible — idéal pour scanner de nombreux hôtes |
--json | Émettre des résultats JSON structurés |
--timeout SECS | Délai d'attente par requête (défaut : 10) |
--no-color | Désactiver la sortie colorée (respecte également NO_COLOR et les terminaux non TTY) |
| Verdict | Signification |
|---|
VULNÉRABLE | Le contournement d'authentification a atteint le gestionnaire vulnérable sans authentification. Appliquer le correctif vers 5.0.8+. |
CORRIGÉ | nginx a rejeté la divergence du chemin normalisé (comportement 5.0.8+). |
NON CONCERNÉ | Aucune empreinte du portail UniFi OS sur la page racine — la cible n'est pas un serveur UniFi OS, donc l'avis ne s'applique pas. Inclut les hôtes qui renvoient 401 sans l'empreinte (par exemple un proxy non lié qui rejette tout). |
NON CONCLUSIF | Hôte UniFi OS confirmé qui n'a pas pu être classé — vérifier la version manuellement. La ligne de détail du verdict indique le cas : (a) le contournement a été bloqué / l'authentification appliquée (401), ou (b) la sonde a renvoyé une réponse inattendue. |
ERREUR | Échec de connexion/délai d'attente/TLS. |