Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
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.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-88776 — Analisi tecnica di CVE-2026-88776, un integer underflow pre-autenticazione nel parser dei record Oracle TNS di nsppe di NetScaler che causa una scrittura fuori dai limiti e il crash del packet engine. | Kitploit
Strumenti/GitHubGitHub/scyrix-llc/cve-2026-88776
Memory ForensicsAnalisi delle VulnerabilitàExploitReverse EngineeringSicurezza di ReteAnalisi di BinariPaper e Ricerca
GitHubscyrix-llc/cve-2026-88776

CVE-2026-88776

Analisi tecnica di CVE-2026-88776, un integer underflow pre-autenticazione nel parser dei record Oracle TNS di nsppe di NetScaler che causa una scrittura fuori dai limiti e il crash del packet engine.

Vedi Repository
21328 giorni faNon ancora revisionato

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-2026-88776: NetScaler nsppe (Pre-Auth OOB Write)

Integer underflow nel parser dei record DataStream / Oracle TNS

Riepilogo

NetScaler è in grado di bilanciare il carico dei database Oracle. Basta puntare un vserver di tipo ORACLE verso di esso e il packet engine inizia a parlare direttamente il protocollo Oracle TNS, analizzando il traffico dei client con un handler integrato. Tale handler mantiene una piccola macchina a stati per ogni connessione, così da ricordare in quale punto si trova all'interno di un record TNS.

Uno di questi stati significa "sono nel mezzo di un record, stanno arrivando altri byte". Quando arriva il segmento successivo, l'handler ne legge la lunghezza e sottrae 10, perché 10 byte di ogni segmento sono header.

Nessuno si è mai chiesto cosa succede se il segmento è più corto di 10 byte.

Inviane uno. Un segmento troncato da 1 a 9 byte entra in quello stato, la lunghezza diventa negativa e, poiché la lunghezza risiede in un registro a 16 bit senza segno, non diventa negativa. Va in wrap su un valore enorme, fino a circa 64 KB. L'handler esegue quindi tranquillamente una memcpy di quella quantità di dati dal tuo pacchetto in un buffer scratch fisso da 0x748 byte in .bss. Il motore non è PIE, quindi l'indirizzo che viene calpestato non si sposta mai.

Non devi effettuare il login. Non ti serve nemmeno un database dietro il vserver, perché l'appliance risponde da sola all'handshake TNS. L'intero attacco è una singola conversazione TCP.

Entrambe le metà sono state dimostrate dal vivo:

  • Invia la lunghezza andata in wrap e il packet engine muore con SIGSEGV, mandando giù il dataplane dell'appliance per circa un minuto. Deterministico, ripetibile, ciclabile.
  • Regola la lunghezza e ottieni la versione silenziosa. I byte dell'attaccante finiscono sopra le variabili globali adiacenti al buffer scratch e il motore continua a funzionare. Si tratta di una primitiva di scrittura, non solo di un crash.

Causa principale

La macchina a stati, e come guidarla

L'handler memorizza il proprio stato per connessione in [pcb+0x15a]. La maggior parte degli stati è banale. Quello che conta qui è 0x1F4, che significa "a metà record, in attesa di continuazione", e si guida una connessione verso di esso usando nient'altro che byte di protocollo ordinari:

record type 6 -> deep-parser state 6 -> byte 0x03 (TTIFUN)
  -> state 0x126 -> TTC function byte 0x5e (OALL8)
  -> jump table 0x23589e0, index 0x59 -> writer at bfe27b:
       [pcb+0x15a] = 0x1F4

Il pacchetto successivo su quella connessione viene quindi inviato su 0x1F4, attraverso bd49a7 fino a bd5362, e arriva qui:

bd5432: memset(0x30a7e60, 0, 0x748)    ; scratch region (ends 0x30a85a8)
bd5445: mov   rcx,[rbp-0x208]          ; inbound packet buffer
bd544c: movzx eax,WORD [rcx+0xf2]      ; u16 wire length of the segment
bd5453: add   eax,0xfffffff6           ; len = len - 10   <== THE UNDERFLOW
bd5456: mov   WORD [0x30a8476],ax      ; wrapped length PERSISTED to .bss
bd545d: movzx edx,ax                   ; memcpy length (1..9 -> 0xfff7..0xffff)
bd5460: mov   rsi,[rcx+0xe8]
bd5467: add   rsi,0xa                  ; src = payload + 10
bd546b: mov   edi,0x30a8075            ; dst = FIXED .bss global
bd5470: call  1b075e0                  ; memcpy: up to ~64 KB OOB write
bd5475: mov   BYTE [0x30a8478],1

Leggilo come una frase. Prendi la lunghezza del segmento. Sottrai 10. Memorizza il risultato, passalo a memcpy, fatto. In nessun momento qualcosa si chiede se "lunghezza meno 10" sia ancora un numero che abbia senso.

La protezione che non c'è

Abbiamo contato ogni riferimento a quel campo di lunghezza in questa funzione. Trenta. Esattamente uno è un controllo, a bd4083, e tutto ciò che fa è confrontare con zero. Un segmento di lunghezza zero viene rifiutato. Ogni altra lunghezza, inclusa da 1 a 9, finisce dritta nella sottrazione.

Il codice crede chiaramente che la macchina a stati abbia consegnato un record sufficientemente completo nel momento in cui viene eseguito lo stato 0x1F4. La macchina a stati non ha mai promesso nulla del genere. Un segmento troncato che arriva come pacchetto a sé stante soddisfa ogni condizione di dispatch e si presenta cinque byte più corto.

La parte davvero esasperante è che il fornitore conosce questa classe di bug. Altrove, nello stesso identico binario, sub_119c940 esegue la stessa aritmetica lunghezza-meno-costante e la protegge con cmp eax,0x3f9 / ja. Il pattern sicuro era lì a disposizione. Questo sito semplicemente non l'ha usato.

Cosa succede quando va in wrap

La destinazione, 0x30a8075, si trova all'interno di una regione scratch di 0x748 byte con solo 0x533 byte di spazio legittimo davanti ad essa. La copia andata in wrap supera quel limite e finisce nelle variabili globali DataStream e di negoziazione adiacenti, con i tuoi byte. E la lunghezza andata in wrap stessa viene persistita a 0x30a8476, dove il codice successivo la rilegge e se ne fida. Questa è una seconda corsia di corruzione, a un passo di distanza dalla memcpy.


Il trigger

La configurazione è una riga di configurazione, un deployment DataStream standard:

add lb vserver v ORACLE <ip> 1521

Nessun backend necessario. L'appliance termina TNS da sola e costruisce il proprio pacchetto Accept, stringa vendor "Netscaler" inclusa.

La conversazione si articola in quattro fasi:

1. TNS Connect (version 0x13A)
     <- the appliance answers Resend(11), then Accept(2), 32 bytes, v0x139

2. one complete, benign TTC round-trip
     (some builds like to glue your runt onto the previous segment;
      this resets the segmentation so the runt lands alone)

3. the arming segment: a TNS Data packet whose declared length is
     actual + 32, carrying TTC bytes {03 5E} (TTIFUN / OALL8)
     -> the state machine latches [pcb+0x15a] = 0x1F4, mid-record

4. the runt: 1-9 bytes, sent as its own TCP segment
     -> passes the zero check, dispatches on 0x1F4
     -> length - 10 wraps
     -> memcpy(0x30a8075, payload+10, ~0xFFF6)
     -> the packet engine dies

I passaggi da 1 a 3 sono pura conversazione. Il passaggio 4 è di cinque byte.


Comportamento di crash osservato

Questo è stato attivato due volte su un'appliance 14.1-73.30, stesso dispositivo, stessa build, due esecuzioni indipendenti. In entrambi i casi il motore dei pacchetti ha ricevuto SIGSEGV con un core dump corrispondente, ns.log ha registrato il segnale 11 all'interno della finestra, e il dataplane è rimasto inattivo per il warm restart di circa 60 secondi.

Il controllo negativo è passato in entrambe le esecuzioni. Eseguendo la conversazione identica ma rendendo il segmento finale 10 byte coerenti, non accade nulla. Il motore lo elabora e prosegue. La lunghezza ridotta è l'unica variabile che conta.

Scarica lo strumento