
pfSense Plus MIM API toolkit b4acd7ca - Élevé - Local - Privilège résiduel - unix sock enroll no JWT
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-api-unix-sock-noauth
Classe : Privilège résiduel Portée : Locale
pfSense Plus MIM API b4acd7ca - Netgate
github.com/Netgate/pfsense-api est l'OpenAPI public plus le Python généré pour pfSense Plus Nexus Multi-instance Management. Ce n'est pas le paquet REST CE. L'exemple d'enrôlement officiel se connecte en HTTPS sur :8443 avec un JWT Bearer, puis déploie en SSH un script POSIX sur chaque pare-feu. Ce script communique avec /var/run/pfnet-controller.sock sans Authorization.
curl --unix-socket /var/run/pfnet-controller.sock -H "Content-Type: application/json" -d "{controller JSON}" http://unix/api/mim/controllers
curl --unix-socket /var/run/pfnet-controller.sock http://unix/api/mim/device/identity
Les fallbacks obsolètes /api/system/controller et /api/system/mim/devid sont identiques : pas de Bearer. La connexion HTTPS émet toujours un JWT. Ce jeton n'est pas appliqué au sock sur l'appareil. Il s'agit d'une frontière de confiance distincte de :8443 plus les groupes mim_*.
Partie 3 de la série Nexus MIM. Après que G1 / G2 ont atterri sur la machine, ce sock est le plan local.
Un processus local capable de connect(2) sur le sock peut enrôler un contrôleur et extraire l'identité de l'appareil sans JWT. De plus, il n'a pas été exécuté. Le DAC réel du sock est inconnu.
| ID | pas encore de CVE |
| Classe | Privilège résiduel |
| Portée | Locale (connect(2) vers /var/run/pfnet-controller.sock) |
| CWE | CWE-306 |
| CVSS | Élevé : 7.8 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H si le mode du sock permet à un autre uid local de se connecter. En toute honnêteté : DAC inconnu, Plus non exécuté. |
| Produit | Netgate/pfsense-api (boîte à outils Plus Nexus MIM) |
| Affecté | main public b4acd7ca21dbca739a530403a1f62a7440f7726f (2026-05-25) |
| Auth | aucune sur les curls d'enrôlement officiels via unix-socket |
| Licence | GNU Affero GPL v3.0 |
| Labo | 127.0.0.1:19121 uniquement. Mock HTTP Unix. Pas d'image Plus. |
L'acteur est tout processus sur l'appareil pfSense capable de connect(2) vers /var/run/pfnet-controller.sock. Pas de TCP distant dans cet exemple (curl --unix-socket uniquement). Le JWT HTTPS :8443 et les groupes mim_* ne s'appliquent pas sur ce fd.
| Méthode | Cible | Privilège |
|---|---|---|
POST officiel device_script sans Authorization | POST http://unix/api/mim/controllers | Intégrité : le mock a accepté le JSON d'enrôlement. Journal de succès authorization_present=false. |
GET officiel device_script sans Authorization | GET http://unix/api/mim/device/identity | Recon : le mock a renvoyé un JSON de forme DeviceIdentity incluant PFSENSE-API-UNIX-SOCK-NOAUTH-WITNESS. |
Même GET avec Authorization: Bearer lab-jwt | même chemin d'identité | Contrôle labo : 401, témoin absent du corps. Distingue présent vs absent. Pas un résultat Plus. |
Ce sont les mêmes opérations OpenAPI que l'échantillon officiel et le tag mim placent sur l'appareil. Prouvé uniquement en tant que protocole, pas en tant que 200 Plus.
| Méthode | Cible | Privilège |
|---|---|---|
POST /mim/controllers (fallback POST /api/system/controller) avec un ControllerIdentity attaquant (key, vpn_pubkey, vpn_listenaddr, vpn_netkey, cert) | SetController | Intégrité : enrôler un contrôleur hostile. Spécification : l'appareil « continuera d'émettre une demande de connexion toutes les 10 secondes » (VPN Netgard vers l'attaquant). |
GET /mim/device/identity (fallback GET /api/system/mim/devid) | GetDeviceIdentity | Recon : clés publiques Noise/VPN de l'appareil, address, texte curl controller_add. |
GET /mim/controllers | GetControllers | Recon : liste des contrôleurs plus les infos de l'appareil (ControllerInfo.noise_secret, clés). |
GET /mim/controllers/id/{key} | GetMIMController | Recon : un enregistrement de contrôleur. |
DELETE /mim/controllers/id/{key} | DeleteMIMController | Intégrité / disponibilité : désenrôler le vrai contrôleur (clé hex ou base64-URL). |
POST /mim/device/pubkey avec privkey / pubkey attaquant | SetDevicePublicKey (DevicePublicKeyOption inclut privkey) | Intégrité : remplacer l'identité ED25519 de l'appareil. La poignée de main du contrôleur fait alors confiance à la clé de l'attaquant. |
N'accorde pas en soi un shell root sur l'hôte. Accorde le plan MIM : qui l'appareil considère comme contrôleur, et la clé privée Noise de l'appareil si le POST pubkey est honoré.
Nécessite : un connect(2) local vers /var/run/pfnet-controller.sock. Le DAC (mode, propriétaire, groupe, SO_PEERCRED) n'est pas dans l'arbre client public. Si le démon se lie en 0600 root, il s'agit déjà d'un accès local root (confused deputy pour un helper, un paquet ou une évasion qui peut voir /var/run). Si le socket est joignable par un autre uid, CVSS 7.8 selon le score.
/mim/controllers sur Nexus HTTPS :8443. Ce port est documenté comme User Manager JWT. Ce reliquat est le fd unix.POST /login émet toujours un Bearer JWT. AuthenticatedClient l'envoie toujours à CONTROLLER_URL+"/api".verify_ssl=True. Les paramètres de chemin percent-encodent ../.security: MISSING sur les 755 opérations est une lacune de schéma, pas un contournement HTTPS non authentifié prouvé.Même pin, plan d'enrôlement distant : pfsense-api-enroll-json-ssh et pfsense-api-enroll-autoadd. Carte de la série : pfsense-api-nexus-mim.
J'ai épinglé Netgate/pfsense-api b4acd7ca21dbca739a530403a1f62a7440f7726f et lu la boucle d'enrôlement officielle : login, GET /mim/controller/identity, stringify, exécution SSH d'un POST/GET sur socket unix, POST /mim/devices. HTTPS utilise AuthenticatedClient(token=...). Les curls sur le socket, non.