
pfSense Plus MIM API toolkit b4acd7ca - Media - Remoto - Privilegi residui - esempi ufficiali verify_ssl=False
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-api-example-ssl-verify
Classe: Privilegio residuo Raggiungibilità: Remota
pfSense Plus MIM API (Netgate/pfsense-api b4acd7ca) - Netgate
I Client / AuthenticatedClient generati impostano verify_ssl=True come predefinito e lo passano a httpx. La documentazione definisce già verify_ssl=False un rischio per la sicurezza e mostra prima un percorso a un bundle PEM. Ogni esempio Python ufficiale e helper_funcs.py li costruiscono ancora con verify_ssl=False. example.js imposta NODE_TLS_REJECT_UNAUTHORIZED=0, quindi l'intero processo Node salta la verifica. Il JSON di login mette username e password in base64. Questo è il contratto OpenAPI, non cifratura. TLS è il livello di riservatezza.
Un peer on-path di :8443 presenta qualsiasi certificato. L'esempio invia comunque il POST a /login. Il sostituto cattura il login admin in base64 e conia un JWT. Quel token è la catena: G4 export-key, G5 ACME dump, G6 fleet JWT, G7 ACB userkey, il previsto php/shell, e il JSON che G1 interpola in SSH.
Questa è la Parte 9 di pfSense Plus MIM API toolkit. Leggi prima questo residuo anche se è Medium. Il JWT rubato è il modo in cui il resto diventa raggiungibile da una workstation che ha copiato example.py.
| ID | nessuna CVE al momento |
| Classe | Privilegio residuo (verifica TLS dell'esempio disattivata) |
| Raggiungibilità | Remota (on-path verso :8443) |
| CWE | CWE-295 |
| CVSS | Media: 6.8 CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N |
| Prodotto | Netgate/pfsense-api (client Plus Nexus MIM; non il pacchetto REST CE) |
| Affetto | main pubblico b4acd7ca21dbca739a530403a1f62a7440f7726f (2026-05-25) esempi ufficiali e helper_funcs.py |
| Auth | l'operatore copia ed esegue un esempio contro il controller; nessun ruolo controller aggiuntivo |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1:19191. Non compone pfSense Plus. |
AC:H è on-path tra la workstation dell'operatore e il controller MIM. UI:R è copiare/eseguire l'esempio.
Vittima: workstation dell'operatore che esegue un esempio ufficiale o helper_funcs.py contro https://controller:8443. Attaccante: on-path verso quell'HTTPS (LAN, DHCP rogue, hop VPN compromesso, ARP). Non Internet non autenticato verso il firewall.
| Metodo | Sink | Privilegio |
|---|---|---|
Presenta qualsiasi certificato mentre il sample esegue il POST su /login o /api/login con verify_ssl=False / NODE_TLS_REJECT_UNAUTHORIZED=0 | httpx verify=False (sample Python) o Node TLS reject-unauthorized 0 | Riservatezza (provata in laboratorio): leggere il JSON di login. Lab: stand-in ha catturato base64 admin / lab-controller-secret (captured_b64_admin=yes). La decodifica è un singolo base64 -d. |
Stesso MITM, 200 LoginResponse | il sample accetta qualsiasi certificato | Riservatezza (provata in laboratorio): rubare l'access JWT. Lab: INJECT ha ottenuto un token che portava PFSENSE-API-EXAMPLE-SSL-VERIFY-WITNESS. |
Stesso MITM, Set-Cookie al login | il sample copia client.get_httpx_client().cookies in AuthenticatedClient | Riservatezza (cookie provato in laboratorio, replay dedotto): refresh JWT di 24 ore. Replay di POST /login/refresh con quel cookie più lo username base64 fino alla scadenza del refresh TTL. Lab ha catturato Set-Cookie: refresh=.... Il refresh contro un controller live non è stato eseguito. |
| Replay del Bearer rubato verso il controller reale (se l'attaccante può anche instradare verso di esso) | Plus MIM /api e /api/device/pfsense/{device_id}/api | Integrità (dedotta): equivalente admin come l'utente loggato su questa API. Lo schema include POST /diag/cmd/php, POST /diag/cmd/shell, POST /diag/editfile, POST /diag/backup/restore, POST /diag/control halt/reboot. Non esercitato qui. Questo lab è uno stand-in del controller, non Plus. |
| Replay del Bearer rubato come leftover 6 (fleet token) | un POST /login JWT riutilizzato per ogni device_id | Integrità (dedotta): parlare al firewall B dopo essersi autenticati come un utente destinato al firewall A. LoginResponse non ha una allow-list per dispositivo. Pack: pfsense-api-fleet-jwt. Plus RBAC non eseguito. |
| Replay del Bearer rubato come leftover 4 | GET /system/certauth/{refid}/export-key, GET /system/certificates/{refid}/export-key, GET /system/certificates/{refid}/export-p12 | Riservatezza (dedotta): estrarre chiavi private CA e leaf, PKCS12 documentato senza protezione password, poi impersonare VPN / WebGUI TLS / IPsec. Pack: pfsense-api-export-key-get. |
| Replay del Bearer rubato come leftover 5 | GET /services/acme | Riservatezza (dedotta): rubare la chiave dell'account Let's Encrypt e le chiavi dei certificati emessi per ogni hostname che il firewall registra. Pack: pfsense-api-acme-key-dump. |
Replay del Bearer rubato, o leak di userkey da un sample che esegue GET su ACB, come leftover 7 | GET /services/acb?userkey= e GET /services/acb/bkp?userkey= | Riservatezza (dedotta): elencare e recuperare i blob di Auto Config Backup (configurazione completa). Pack: pfsense-api-acb-userkey. |
Modellare il JSON ControllerSummary verso leftover 1 | MITM di verify_ssl=False HTTPS fornisce il JSON che example-add-devices.py fa il quote-escape e poi .format in SSH | Integrità (dedotta): $() / backtick / newline in un campo del controller vengono eseguiti come SSHUSER su ogni indirizzo in pfsense_addresses. Pack: pfsense-api-enroll-json-ssh. |
| Iniettare risposte verso il client | skip-verify accetta qualsiasi certificato | Integrità (token provato in laboratorio, fleet dedotta): coniare un JWT che il sample manterrà. Lab: INJECT token con il witness. Liste di dispositivi false / progresso di upgrade / login riuscito contro un sample live sono lo stesso gate. |
POST /diag/control, POST firmware, restore di un backup corrotto (dopo Bearer rubato) | superficie admin prevista una volta che TLS è andato | Disponibilità (dedotta): halt / reboot / immagine corrotta. Stesso Bearer. Non testato in laboratorio. |
Provato in laboratorio vs dedotto: fallimento dell'handshake CONTROL, token INJECT e login admin base64 catturato sono provati in laboratorio su 127.0.0.1:19191. Il replay di quel Bearer su un controller Plus live, diag php/shell, G4-G7, il JSON shaping G1 e la coniazione di nuovi access JWT tramite refresh-cookie sono dedotti dall'OpenAPI e dai sample.