
pfSense Plus MIM API toolkit b4acd7ca - Alta - Local - Privilegio residual - unix sock enroll sin JWT
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-api-unix-sock-noauth
Clase: Privilegio residual Alcance: Local
pfSense Plus MIM API b4acd7ca - Netgate
github.com/Netgate/pfsense-api es la OpenAPI pública más el Python generado para pfSense Plus Nexus Multi-instance Management. No es el paquete REST de CE. El ejemplo oficial de enrolamiento inicia sesión en HTTPS :8443 con un Bearer JWT, y luego envía por SSH un script POSIX a cada firewall. Ese script se comunica con /var/run/pfnet-controller.sock sin 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
Los fallbacks obsoletos /api/system/controller y /api/system/mim/devid son iguales: sin Bearer. El inicio de sesión HTTPS sigue emitiendo un JWT. Ese token no se aplica al sock del dispositivo. Esta es una frontera de confianza separada de :8443 más los grupos mim_*.
Parte 3 de la serie Nexus MIM. Después de que G1 / G2 aterricen en la máquina, este sock es el plano local.
Un proceso local que pueda connect(2) al sock puede enrolar un controlador y volcar la identidad del dispositivo sin JWT. Además, no se ejecutó. El DAC real del sock es desconocido.
| ID | sin CVE todavía |
| Clase | Privilegio remanente |
| Alcance | Local (connect(2) a /var/run/pfnet-controller.sock) |
| CWE | CWE-306 |
| CVSS | Alto: 7.8 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H si el modo del sock permite que otro uid local se conecte. Honestamente: DAC desconocido, Plus no ejecutado. |
| Producto | Netgate/pfsense-api (kit de herramientas Plus Nexus MIM) |
| Afectado | main público b4acd7ca21dbca739a530403a1f62a7440f7726f (2026-05-25) |
| Autenticación | ninguna en los curls oficiales de enrolamiento por unix-socket |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1:19121. Mock HTTP de Unix. Sin imagen Plus. |
El actor es cualquier proceso en el dispositivo pfSense que pueda connect(2) a /var/run/pfnet-controller.sock. No es TCP remoto en este ejemplo (solo curl --unix-socket). El JWT de HTTPS :8443 y los grupos mim_* no aplican en este fd.
| Método | Destino | Privilegio |
|---|---|---|
POST oficial de device_script sin Authorization | POST http://unix/api/mim/controllers | Integridad: el mock aceptó el JSON de enrolamiento. Registro de aciertos authorization_present=false. |
GET oficial de device_script sin Authorization | GET http://unix/api/mim/device/identity | Reconocimiento: el mock devolvió JSON con forma de DeviceIdentity incluyendo PFSENSE-API-UNIX-SOCK-NOAUTH-WITNESS. |
El mismo GET con Authorization: Bearer lab-jwt | misma ruta de identidad | Control de laboratorio: 401, testigo no presente en el cuerpo. Distingue presente vs ausente. No es un resultado de Plus. |
Estas son las mismas operaciones de OpenAPI que la muestra oficial y la etiqueta mim colocan en el dispositivo. Probado solo como protocolo, no como un 200 de Plus.
| Método | Destino | Privilegio |
|---|---|---|
POST /mim/controllers (fallback POST /api/system/controller) con ControllerIdentity del atacante (key, vpn_pubkey, vpn_listenaddr, vpn_netkey, cert) | SetController | Integridad: enrolar un controlador hostil. Especificación: el dispositivo "seguirá emitiendo una solicitud de conexión cada 10 segundos" (VPN de Netgard hacia el atacante). |
GET /mim/device/identity (fallback GET /api/system/mim/devid) | GetDeviceIdentity | Reconocimiento: claves públicas Noise/VPN del dispositivo, address, texto curl de controller_add. |
GET /mim/controllers | GetControllers | Reconocimiento: listar controladores más información del dispositivo (ControllerInfo.noise_secret, claves). |
GET /mim/controllers/id/{key} | GetMIMController | Reconocimiento: un registro de controlador. |
DELETE /mim/controllers/id/{key} | DeleteMIMController | Integridad / disponibilidad: desenrolar el controlador real (clave hex o base64-URL). |
POST /mim/device/pubkey con privkey / pubkey del atacante | SetDevicePublicKey (DevicePublicKeyOption incluye privkey) | Integridad: reemplazar la identidad ED25519 del dispositivo. El handshake del controlador entonces confía en la clave del atacante. |
No otorga por sí mismo un shell root en el host. Otorga el plano MIM: en quién confía el dispositivo como controlador, y la clave privada Noise del dispositivo si se honra el POST de pubkey.
Requiere: connect(2) local a /var/run/pfnet-controller.sock. DAC (mode, owner, group, SO_PEERCRED) no está en el árbol de cliente público. Si el daemon se enlaza a 0600 root, esto ya es root local (confused deputy para un helper, paquete o escape que pueda ver /var/run). Si el sock es alcanzable por otro uid, CVSS 7.8 según la puntuación.
/mim/controllers en Nexus HTTPS :8443. Ese puerto está documentado como User Manager JWT. Este remanente es el fd unix.POST /login sigue emitiendo un Bearer JWT. AuthenticatedClient todavía lo envía a CONTROLLER_URL+"/api".verify_ssl=True. Los parámetros de ruta codifican percentualmente ../.security: MISSING en las 755 operaciones es un vacío de esquema, no un salto HTTPS no autenticado probado.Mismo pin, plano de enrolamiento remoto: pfsense-api-enroll-json-ssh y pfsense-api-enroll-autoadd. Mapa de la serie: pfsense-api-nexus-mim.
Fijé Netgate/pfsense-api b4acd7ca21dbca739a530403a1f62a7440f7726f y leí el bucle de enrolamiento oficial: login, GET /mim/controller/identity, stringify, SSH exec de unix-socket POST/GET, POST /mim/devices. HTTPS usa AuthenticatedClient(token=...). Los curls del sock no.