pfSense Plus MIM API toolkit b4acd7ca - High - Remote - Privilege leftover - example-add-devices.py JSON into SSH
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · pfsense-api-enroll-json-ssh
Classe: Privilegio residuo Portata: Remota
pfSense Plus MIM API toolkit (b4acd7ca) - Netgate
example-add-devices.py è il modo documentato per registrare il controller Nexus su ogni dispositivo pfSense Plus via SSH. Esegue json.dumps su GET /mim/controller/identity, sostituisce solo ", poi applica .format a quel blob due volte in uno script POSIX curl -d con doppi apici. Paramiko exec_command esegue lo script come SSHUSER (default di esempio admin) su ogni indirizzo in pfsense_addresses.
json.dumps più replace('"', '\\"') mantiene le virgolette chiuse. $(), i backtick e ${...} non sono metacaratteri JSON. Restano attivi all'interno della stringa -d con doppi apici ancora aperta. OpenSSH exec è una shell. Questo è il residuo.
Questo non è il pacchetto REST CE di terze parti. È il client OpenAPI ufficiale e gli esempi per il controller pfSense Plus Nexus Multi-instance Management. Non ho composto Plus. Il laboratorio è l'interpolazione fissata più un mock di /var/run/pfnet-controller.sock.
| ID | nessuna CVE al momento |
| Classe | Privilegio residuo (JSON del controller nell'SSH di enrollment) |
| Portata | Remota (on-path verso CONTROLLER_URL mentre l'esempio imposta verify_ssl=False, oppure un writer dei campi stringa di ControllerSummary) |
| CWE | CWE-78 |
| CVSS | Alto: 8.1 CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H |
| Prodotto | Netgate/pfsense-api (Plus MIM toolkit) |
| Affetto | main pubblico b4acd7ca21dbca739a530403a1f62a7440f7726f example-add-devices.py |
| Auth | l'operatore esegue l'esempio documentato. L'attaccante è on-path, oppure può scrivere le stringhe di riepilogo. Il login al controller avviene comunque prima. |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1:19101. Nessuna immagine Plus. |
Parte 1 della serie sui residui Nexus MIM. Correlati: enroll-autoadd, unix-sock-noauth, example-ssl-verify (G9 è il modo in cui un peer on-path modella questo JSON), fleet-jwt, export-key-get.
Il residuo è la sostituzione di comandi all'interno della stringa -d con doppi apici ancora aperta. json.dumps più il passaggio sulle virgolette mantengono la stringa chiusa. $(), i backtick e ${...} sopravvivono ed eseguono come SSHUSER quando OpenSSH esegue lo script.
| Metodo | Sink | Privilegio | Provato in laboratorio o dedotto |
|---|---|---|---|
Inserire $() (o backtick / ${...}) in un campo stringa ControllerSummary, poi lasciare che l'operatore esegua example-add-devices.py | controller_info.replace('"', '\\"') poi device_script.format(...) poi sshclient.exec_command(device_script) (example-add-devices.py ~104-161) | Shell come SSHUSER (default di esempio admin; l'SSH admin di pfSense è tipicamente equivalente a root) su ogni indirizzo in pfsense_addresses | Provato in laboratorio sull'interpolazione: INJECT vpn_listenaddr=$(printf %s PFSENSE-API-ENROLL-JSON-SSH-WITNESS >/oracle/witness) è sopravvissuto all'escape solo-virgolette (dollar-paren-survived=yes) e ha scritto il witness (inject-oracle=yes). Paramiko/SSH stesso non è in questo compose. |
TLS MITM di GET /api/mim/controller/identity mentre il campione usa verify_ssl=False | Stesso parsing di ControllerSummary poi lo stesso script | Stessa shell. Tutti i campi di ControllerSummary sono str o Unset, quindi un body JSON MITM che effettua il type-parse è sufficiente. | Dedotto dal campione (example-add-devices.py login Client e AuthenticatedClient impostano entrambi verify_ssl=False). Il laboratorio invia direttamente l'oggetto summary. Correlato: example-ssl-verify. |
Scrivere caratteri di sostituzione in name o vpn_listenaddr sul controller, attendere il prossimo enroll | Stesso sink | Stessa shell quando un operatore esegue successivamente il campione | Dedotto. Richiede una scrittura preventiva di quei campi (già controller-admin, oppure il correlato unix-sock-noauth). |
Stessa shell, chiavi extra tramite ControllerSummary.additional_properties | Lo stesso dump include chiavi MITM extra (to_dict copia i residui dopo from_dict) | I campi extra finiscono in -d e nella shell | Dedotto da to_dict. Il laboratorio inietta solo tramite vpn_listenaddr. |
| Metodo | Sink | Privilegio | Provato in laboratorio o dedotto |
|---|---|---|---|
| Leggere lo stdout della workstation di enrollment | print("CONTROLLER_SUMMARY:", controller_info) | Identità del controller key, vpn_pubkey / vpn_netkey / indirizzi di ascolto di Netgard | Dedotto dalla print del campione. Il laboratorio non stampa un blob di un controller live. |
| Sniffare o MITM del canale exec SSH | Il payload di exec_command(device_script) è il JSON -d di curl | Stessa identità del controller sul filo verso ogni dispositivo | Dedotto. AutoAddPolicy su quel canale è un report correlato. |
| Caso CONTROL sul gadget | POST /case name=control | Un vpn_listenaddr onesto raggiunge il socket unix invariato | Provato in laboratorio. 192.0.2.10:51820 inviato così com'è, nessun oracle (control-clean=yes). |
| Metodo | Sink | Privilegio | Provato in laboratorio o dedotto |
|---|---|---|---|
Comando iniettato come SSHUSER | Stesso exec_command | Fermare pfnet-controller, cancellare l'enrollment, riavviare, o altrimenti escludere il dispositivo da MIM | Dedotto come effetto collaterale della shell. Il laboratorio scrive solo il file witness. |
Richiede: il percorso del campione ufficiale (enroll dell'operatore). UI:N per il peer on-path una volta che quel campione è in esecuzione. Il login al controller avviene comunque prima.