Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-88776 — Technische Analyse von CVE-2026-88776, einem Pre-Auth-Integer-Underflow im Oracle-TNS-Record-Parser von NetScaler nsppe, der einen Out-of-Bounds-Write und einen Absturz der Packet Engine verursacht. | Kitploit
Tools/GitHubGitHub/scyrix-llc/cve-2026-88776
SpeicherforensikSchwachstellenanalyseExploitationReverse EngineeringNetzwerksicherheitBinäranalysePapers & Forschung
GitHubscyrix-llc/cve-2026-88776

CVE-2026-88776

Technische Analyse von CVE-2026-88776, einem Pre-Auth-Integer-Underflow im Oracle-TNS-Record-Parser von NetScaler nsppe, der einen Out-of-Bounds-Write und einen Absturz der Packet Engine verursacht.

Repository anzeigen
213vor 28 TagenNoch nicht geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-88776: NetScaler nsppe (Pre-Auth OOB Write)

Integer-Unterlauf im DataStream-/Oracle-TNS-Record-Parser

Zusammenfassung

NetScaler kann Oracle-Datenbanken per Load-Balancing verteilen. Richtet man einen vserver vom Typ ORACLE darauf, beginnt die Packet Engine selbst das Oracle-TNS-Protokoll zu sprechen und parst den Client-Verkehr mit einem eingebauten Handler. Dieser Handler unterhält pro Verbindung eine kleine Zustandsmaschine, damit er sich merkt, wo innerhalb eines TNS-Records er sich befindet.

Einer dieser Zustände bedeutet: „Ich bin mitten in einem Record, es kommen weitere Bytes." Wenn das nächste Segment eintrifft, liest der Handler dessen Länge und subtrahiert 10, denn 10 Bytes jedes Segments sind Header.

Niemand hat je gefragt, was passiert, wenn das Segment kürzer als 10 Bytes ist.

Schickt ihm eines. Ein Zwergsegment von 1 bis 9 Bytes läuft in diesen Zustand, die Länge wird negativ, und weil die Länge in einem vorzeichenlosen 16-Bit-Register liegt, wird sie nicht negativ. Sie läuft über zu einem gewaltigen Wert, bis zu etwa 64 KB. Der Handler memcpy't dann fröhlich diese Menge an Daten aus dem Paket in einen festen Scratch-Puffer von 0x748 Bytes in .bss. Die Engine ist nicht PIE, sodass sich die überschriebene Adresse nie verschiebt.

Man muss sich nicht anmelden. Man braucht nicht einmal eine Datenbank hinter dem vserver, denn die Appliance beantwortet den TNS-Handshake selbst. Der gesamte Angriff ist eine einzige TCP-Konversation.

Beide Hälften wurden live demonstriert:

  • Feuert man die umgelaufene Länge ab, stirbt die Packet Engine mit SIGSEGV und reißt die Dataplane der Appliance für etwa eine Minute mit. Deterministisch, wiederholbar, in einer Schleife ausführbar.
  • Stimmt man die Länge ab, erhält man die stille Variante. Angreifer-Bytes landen über den Globals, die neben dem Scratch-Puffer liegen, und die Engine läuft weiter. Das ist ein Write-Primitive, nicht nur ein Absturz.

Ursache

Die Zustandsmaschine und wie man sie steuert

Der Handler speichert seinen Zustand pro Verbindung unter [pcb+0x15a]. Die meisten Zustände sind langweilig. Der hier relevante ist 0x1F4, was „mitten im Record, warte auf Fortsetzung" bedeutet, und man steuert eine Verbindung dorthin allein mit gewöhnlichen Protokoll-Bytes:

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

Das nächste Paket auf dieser Verbindung verzweigt dann bei 0x1F4, über bd49a7 nach bd5362, und landet hier:

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

Lies es wie einen Satz. Nimm die Länge des Segments. Subtrahiere 10. Speichere das Ergebnis, übergib es an memcpy, fertig. An keiner Stelle wird gefragt, ob „Länge minus 10" noch eine Zahl ist, die Sinn ergibt.

Die Schutzprüfung, die es nicht gibt

Wir haben jeden Verweis auf dieses Längenfeld in dieser Funktion gezählt. Dreißig davon. Genau einer ist eine Prüfung, bei bd4083, und alles, was sie tut, ist ein Vergleich mit null. Ein Segment der Länge null wird abgelehnt. Jede andere Länge, einschließlich 1 bis 9, läuft direkt in die Subtraktion.

Der Code geht offensichtlich davon aus, dass die Zustandsmaschine bis zum Zeitpunkt, an dem Zustand 0x1F4 ausgeführt wird, einen ausreichend vollständigen Datensatz geliefert haben wird. Die Zustandsmaschine hat nie etwas Derartiges versprochen. Ein zu kurzes Segment, das als eigenes Paket ankommt, erfüllt jede Dispatch-Bedingung und taucht fünf Bytes zu kurz auf.

Der wirklich ärgerliche Teil ist, dass der Hersteller diese Fehlerklasse kennt. An anderer Stelle in genau demselben Binary führt sub_119c940 die identische Arithmetik Länge-minus-Konstante aus und schützt sie mit cmp eax,0x3f9 / ja. Das sichere Muster lag direkt vor der Nase. Diese Stelle hat es einfach nicht verwendet.

Was du triffst, wenn es überläuft

Das Ziel, 0x30a8075, liegt innerhalb eines 0x748 Byte großen Scratch-Bereichs, mit nur 0x533 Byte legitimem Platz davor. Die umgebrochene Kopie schießt darüber hinaus in die DataStream- und Negotiation-Globals nebenan, mit deinen Bytes. Und die umgebrochene Länge selbst wird nach 0x30a8476 persistiert, wo späterer Code sie zurückliest und ihr vertraut. Das ist eine zweite Korruptionsspur, einen Schritt entfernt vom memcpy.


Der Auslöser

Das Setup ist eine Zeile Konfiguration, ein Standard-DataStream-Deployment:

add lb vserver v ORACLE <ip> 1521

Kein Backend erforderlich. Die Appliance beendet TNS selbst und baut ihr eigenes Accept-Paket, inklusive der Vendor-Zeichenkette „Netscaler".

Die Konversation durchläuft vier Schritte:

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

Die Schritte 1 bis 3 sind reine Konversation. Schritt 4 besteht aus fünf Bytes.


Beobachtetes Absturzverhalten

Dies wurde zweimal auf einer 14.1-73.30-Appliance ausgelöst, dieselbe Box, derselbe Build, zwei unabhängige Durchläufe. Beide Male erhielt die Paket-Engine SIGSEGV mit einem passenden Core-Dump, ns.log verzeichnete Signal 11 innerhalb des Zeitfensters, und die Dataplane blieb für den etwa 60-sekündigen Warm-Neustart außer Betrieb.

Die Negativkontrolle bestand beide Durchläufe. Führt man die identische Konversation aus, aber macht das letzte Segment zu kohärenten 10 Bytes, passiert nichts. Die Engine verarbeitet es und macht weiter. Die Länge des Runt ist die einzige Variable, die zählt.

Tool herunterladen