
Cacti 1.2.22 iniezione di comandi non autenticata
| Campo | Dettagli |
|---|---|
| Prodotto | Cacti |
| Versione interessata | 1.2.22 |
| Vulnerabilità | Iniezione di comandi OS non autenticata |
| CVE | CVE-2022-46169 |
| CWE | CWE-77 — Iniezione di comandi |
| Gravità | Critica |
| CVSS v3.1 | 9.8 |
| Vettore di attacco | Rete |
| Autenticazione | Nessuna |
| Interazione utente | Nessuna |
| Impatto | Riservatezza / Integrità / Disponibilità |
| Versione corretta | 1.2.23 |
| Componente vulnerabile | remote_agent.php |
| Componente aggiuntivo | lib/functions.php |
| Azione vulnerabile principale | polldata |
Il vettore CVSS pubblicato è:
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
L'avviso ufficiale lo valuta 9.8 Critico. ([GitHub][1])
In realtà ci sono due bug concatenati.
Fase 1 — Bypass dell'autorizzazione
remote_agent.php di Cacti accetta richieste senza autenticazione normale, ma tenta di determinare se il richiedente è un poller autorizzato.
Il flusso di autorizzazione effettivamente fa:
Richiesta HTTP
│
▼
remote_agent.php
│
▼
remote_client_authorized()
│
▼
get_client_addr()
│
▼
gethostbyaddr()
│
▼
Confronto hostname nella tabella poller
Il problema è get_client_addr().
Nella versione 1.2.22 esamina numerose variabili server derivate da HTTP, inclusi gli header forwarded-client-IP. L'avviso spiega che i valori HTTP_* controllati dall'attaccante possono influenzare l'IP restituito da questa funzione. ([GitHub][1])
Ciò significa che l'applicazione può essere indotta a credere:
Attaccante
↓
"il mio IP è il server Cacti"
↓
gethostbyaddr()
↓
Hostname del server Cacti
↓
corrisponde alla tabella poller
↓
AUTORIZZATO
Quindi l'attaccante non ha bisogno di un account Cacti legittimo.
Dopo aver bypassato il controllo di autorizzazione, la funzionalità interessante dell'endpoint è l'azione polldata.
Il percorso di esecuzione rilevante è approssimativamente:
remote_agent.php
│
▼
polldata
│
▼
poll_for_data()
│
├── host_id
├── local_data_ids
└── poller_id
│
▼
Ricerca poller_item
│
▼
POLLER_ACTION_SCRIPT_PHP
│
▼
proc_open()
│
▼
Esecuzione comandi OS
L'errore importante è la gestione di poller_id.
L'applicazione lo recupera utilizzando:
get_nfilter_request_var()
piuttosto che imporre che sia un intero.
Quel valore controllato dall'attaccante diventa infine parte di un comando passato a proc_open() di PHP. L'avviso ufficiale identifica esplicitamente questo come la primitiva di iniezione di comandi. ([GitHub][1])
Concettualmente:
input controllato dall'attaccante
↓
poller_id
↓
concatenazione di stringhe
↓
proc_open()
↓
comando del sistema operativo
Questa è la parte critica della vulnerabilità.
La cosa interessante per la tua analisi del PoC è che nessuno dei due bug da solo racconta l'intera storia.
È una catena di vulnerabilità:
┌──────────────────────────┐
│ Attaccante non autenticato │
└────────────┬─────────────┘
│
▼
remote_agent.php
│
▼
Bypass dell'autorizzazione
tramite logica IP client
│
▼
polldata
│
▼
Ricerca poller_item
│
▼
POLLER_ACTION_SCRIPT_PHP
│
▼
input dell'attaccante
→ poller_id
│
▼
proc_open()
│
▼
Esecuzione di comandi
│
▼
RCE
Questa è una distinzione molto importante da fare nel tuo write-up:
CVE-2022-46169 non è semplicemente "un parametro difettoso in remote_agent.php." È una vulnerabilità concatenata di bypass dell'autorizzazione + iniezione di comandi.
L'avviso ufficiale conferma che la condizione di esecuzione vulnerabile richiede un poller_item la cui azione è POLLER_ACTION_SCRIPT_PHP. ([GitHub][1])
Il tuo PoC dovrebbe documentare esplicitamente questo perché è un dettaglio analitico importante.
Il target necessita di un poller_item appropriato configurato con:
POLLER_ACTION_SCRIPT_PHP
L'avviso di Cacti nota che questo è comune nelle installazioni di produzione perché modelli predefiniti come Device - Uptime e Device - Polling Time possono creare queste voci. ([GitHub][1])
Quindi non scrivere:
"Ogni installazione di Cacti 1.2.22 è automaticamente sfruttabile."
Un'affermazione tecnicamente più accurata è:
Cacti 1.2.22 è vulnerabile e l'esecuzione di comandi riuscita dipende dalla presenza di una configurazione
poller_itemappropriata.
host_id e local_data_id contanopoll_for_data() non esegue semplicemente il poller_id fornito.
Prima interroga poller_item utilizzando valori corrispondenti a:
host_id
local_data_id
Poi esamina l'azione dell'elemento risultante.
La condizione vulnerabile è effettivamente:
host_id
+
local_data_id
↓
poller_item
↓
action == POLLER_ACTION_SCRIPT_PHP
↓
percorso di esecuzione vulnerabile
L'avviso originale nota che questi identificatori possono essere scoperti perché le voci rilevanti esistono nel database dell'applicazione e che voci adatte probabilmente esistono nelle installazioni produttive. ([GitHub][1])
Per un PoC pubblico, dimostrerei questo prerequisito esplicitamente piuttosto che nasconderlo.
Per qualcosa che pubblichi, raccomando di far dimostrare al PoC l'esecuzione di comandi senza dare ai lettori un payload di reverse-shell armato.
Ad esempio, struttura la tua dimostrazione come:
1. Distribuisci Cacti 1.2.22 in una VM isolata
2. Configura un poller_item usando POLLER_ACTION_SCRIPT_PHP
3. Conferma che remote_agent.php sia raggiungibile
4. Dimostra che la decisione di autorizzazione viene influenzata
5. Raggiungi il percorso di esecuzione polldata
6. Usa un marcatore di esecuzione di comandi innocuo
7. Cattura le prove risultanti dall'applicazione/log
8. Aggiorna a 1.2.23
9. Ripeti il test
10. Dimostra che la vulnerabilità non è più sfruttabile
Questo ti dà una dimostrazione di vulnerabilità legittima senza trasformare il write-up in un'arma RCE Internet pronta all'uso.
Puoi dividere il codice vulnerabile in tre aree.
remote_agent.phpResponsabile dell'esposizione della funzionalità remote-agent e dell'invio dell'azione richiesta.