
OPNsense 26.7.6 - Élevé - À distance - Privilège résiduel - UidField uid 0
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · opnsense-uidfield-system-uid0
Classe : Résidu de privilège Portée : Distante
OPNsense core 26.7.6 (a842fe48) - opnsense.org
page-system-usermanager délégué en deux étapes scope=system puis uid=0. UidField::setValue n'attribue automatiquement 2000+ que tant que le scope n'est pas system. setNodes applique uid avant scope, donc un seul ajout ne peut pas estampiller 0. Le second POST le peut. auth sync user exécute ensuite pw useradd -o -u 0 avec le home /root et le groupe wheel. Les clés autorisées atterrissent dans /root/.ssh/authorized_keys. Le privilège est System: Access: Management, pas page-all.
| ID | pas encore de CVE |
| Classe | Résidu de privilège |
| Portée | Distante (WebGUI authentifié / clé API locale) |
| CWE | CWE-269 / CWE-284 |
| CVSS | Élevé : 8.8 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Produit | OPNsense core (Deciso B.V.) |
| Affecté | OPNsense core 26.7.6 (a842fe48c21288d11a422cb944678e8eb308becf) UidField / user-manager |
| Auth | Session WebGUI ou clé API locale avec page-system-usermanager |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
J'ai épinglé le tag 26.7.6 « Xenial Xenops ». Le lab est un gadget PHP du UidField::setValue épinglé plus local_user_set, identité loopback 127.0.0.1:18810. stable/26.7 a annulé l'écriture UID-0 sous ea4f01fe le 2026-10-09. Cette annulation n'est pas cette épingle. Pas de GHSA.
| Méthode | Sink | Privilège |
|---|---|---|
ajout en deux étapes scope=system puis uid=0 puis auth sync user | épingle UidField::setValue puis stub pw useradd -o -u 0 (auth.inc:345-397) | Intégrité (prouvé en lab) : second UID Unix 0, home /root, groupe wheel. Lab : after-add=2000 after-set=0 pw-o-u0=yes. |
| même set + authorizedkeys | file_put_contents /root/.ssh/authorized_keys (auth.inc:407-416) | Intégrité (prouvé en lab) : témoin dans /root/.ssh/authorized_keys. |
SSH sous ce nom si sshd est actif (AllowGroups wheel ; PermitRootLogin ne s'applique pas à un nom d'utilisateur non-root) | sshd | Recon + intégrité (déduit) : connexion sous le nouveau nom wheel, lecture de /root. Le gadget n'a pas démarré sshd. |
mêmes POSTs avec scope=user uid=0 | attribution automatique 2000+ par UidField | Négatif (prouvé en lab) : l'uid reste 2000. scope-user-uid0-ignored=yes. |
set de l'uuid root d'origine uid=80 | pw usermod -u 80 | Intégrité + disponibilité (déduit) : déplacer le root d'origine hors de l'UID 0. Le gadget n'a pas fait de usermod sur root. |
set de l'uuid root name=hax + scope=user | vérification de renommage contournée ; auth sync user sur le nouveau nom | Intégrité (déduit) : renommage d'utilisateur système que la vérification de 26.7.6 était censée empêcher. |
Prouvé en lab vs déduit : l'UID 0 en deux étapes, pw useradd -o -u 0, le chemin des clés et l'ignorance de scope=user sont des SUCCÈS en lab. L'acceptation par un sshd réel et le usermod/renommage du root d'origine sont déduits. Gadget, pas une VM OPNsense complète.
Nécessite : une session WebGUI ou une clé API locale avec page-system-usermanager. CSRF sur le chemin de session. Pas page-all. Le config.xml.sample par défaut n'accorde page-all qu'au groupe admins.
| Surface | Lab |
|---|---|
POST /api/auth/user/* sans page-system-usermanager | ACL fermée |
user-config-readonly | save() toujours throwReadOnly() |
| Upload CSV | supprime uid/scope |
| CVE-2026-44194 email-as-shell | mwexecf %s + regex email |
| Page mot de passe | liée à la session |
page-all faisant le même POST | fonctionnalité du changelog sur cette épingle |
| Non authentifié | fermé |
su Unix avec * dans master.passwd | le hash GUI reste dans config.xml sauf si l'installateur force |
Pas de non-authentifié. Pas de page-all requis. 26.7.6 présentait l'UID choisi pour les utilisateurs de scope système comme une fonctionnalité admin. La marche non appariée est un user-manager délégué sans page-all.
cd lab
./run.sh
Loopback 127.0.0.1:18810. Projet Compose opnsense-uidfield-system-uid0. Image issue de l'épingle 26.7.6. Témoin OPNSENSE-UIDFIELD-SYSTEM-UID0-WITNESS. Dernière ligne :
SUCCESS opnsense-uidfield-system-uid0 two-step-uid=0 scope-user-uid0-ignored=yes pw-o-u0=yes keys=/root/.ssh/authorized_keys OPNSENSE-UIDFIELD-SYSTEM-UID0-WITNESS
Rejeter l'UID 0 (et les UID de service en collision) sauf si l'appelant est un administrateur complet. Appliquer scope avant uid dans setNodes, ou refuser un POST qui modifie les deux. Conserver la vérification de renommage de 26.7.6 sur le scope pré-setNodes, pas sur celui posté. ea4f01fe a ensuite annulé l'écriture UID-0 sur stable/26.7 ; ce commit n'est pas cette épingle.
a842fe48c21288d11a422cb944678e8eb308becfUidField.phpauth.inc local_user_setea4f01fe sur stable/26.7