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-88773 — Technische Analyse einer NetScaler-nsppe-Schwachstelle für Request Smuggling durch Integer-Wrap bei HTTP/1.1-Chunk-Größen, mit Disassembly, PoC-Abläufen auf Wire-Ebene und Firmware-Patch-Diff. | Kitploit
Tools/GitHubGitHub/scyrix-llc/cve-2026-88773
SchwachstellenanalyseExploitationReverse EngineeringWebanwendungs-ExploitationWebsicherheitBinäranalysePapers & ForschungFirmware-Analyse
GitHubscyrix-llc/cve-2026-88773

CVE-2026-88773

Technische Analyse einer NetScaler-nsppe-Schwachstelle für Request Smuggling durch Integer-Wrap bei HTTP/1.1-Chunk-Größen, mit Disassembly, PoC-Abläufen auf Wire-Ebene und Firmware-Patch-Diff.

11vor 1 MonatNoch nicht geprüft
Repository anzeigen
Webseite

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

CVE-2026-88773: NetScaler nsppe (HTTP Smuggle)

32-Bit-Chunk-Size-Akkumulator-Überlauf im HTTP/1.1-Parser

TL;DR

Der nsppe-HTTP/1.1-Parser für Chunked-Bodies liest das Chunk-Size-Feld in ein 32-Bit-Register und prüft nie auf Überlauf. Bei neun oder mehr Hex-Ziffern läuft der Wert stillschweigend über: 100000005 (2^32 + 5) wird als Chunk-Größe von 5 verarbeitet.

Das ist ein lustiger Parser-Bug, bis man sich vergegenwärtigt, was NetScaler mit dem Body macht: Es leitet die Chunked-Framing des Clients exakt wie empfangen an das Backend weiter, entscheidet aber anhand seines eigenen übergelaufenen Werts, wo die Anfrage endet. Der Proxy glaubt also, Anfrage #1 sei nach fünf Body-Bytes abgeschlossen, während ein korrekt arbeitendes Backend, das dieselben Bytes liest, 4.294.967.301 berechnet und sich auf einen 4-GB-Body einstellt, der nie ankommen wird. Zwei Maschinen, ein Byte-Stream, zwei unterschiedliche Auffassungen darüber, wo eine Anfrage endet.

Alles nach NetScalers Version von „das Ende" wird als neue pipelined Anfrage auf derselben Client-Verbindung neu klassifiziert und dann unabhängig über die gemeinsame Proxy-zu-Backend-Verbindung weitergeleitet.

Was dabei herauskommt, hängt vom eigenen Parser des Backends ab:

  • Backend schneidet ebenfalls auf 32 Bit ab: Die geschmuggelten Bytes werden als unabhängige Anfrage ausgeführt. Klassischer Prefix-Hijack.
  • Backend parst korrekt: Harte Desynchronisation, die Verbindung hängt an einem 4-GB-Body fest, der nie ankommt. Connection-Pool-Erschöpfungs-DoS.

Eine unauthentifizierte Anfrage. Standardkonfiguration. Keine Vorbedingungen außer der Erreichbarkeit eines HTTP-vServers.


Ursache

Der Hex-Parser für die Chunk-Größe

Die Aufgabe des Parsers ist einfach: eine Chunk-Size-Zeile wie 1a3f\r\n in eine Zahl umwandeln. Er nimmt den Puffer in rdi mit seiner Länge in esi, akkumuliert den Hex-Wert in den 32-Bit-Slot bei *rdx (Eingabe und Ausgabe, sodass eine über zwei Pakete aufgeteilte Größe sauber fortgesetzt wird), überspringt Leerraum und verlangt das abschließende \r\n. Er antwortet mit der Anzahl verbrauchter Bytes, 0 für „mehr Daten nötig" oder -1 für fehlerhaft.

Die gesamte Schleife, klein genug, um den Bug mit bloßem Auge zu erkennen:

20af5e0: movzx  eax, BYTE PTR [rbx]
20af5e3: test   BYTE PTR [rax+rax*1+0x2746c80], 0x10   ; ctype: hex digit?
20af5eb: je     20af60b
20af5ed: mov    ecx, r11d
20af5f0: shl    ecx, 0x4                               ; value <<= 4
20af5f3: movzx  r11d, BYTE PTR [rax+0x2746b80]         ; hexval(digit)
20af5fb: add    r11d, ecx                              ; value = value*16 + d
20af5fe: inc    rbx
20af601: dec    r8d
20af604: jne    20af5e0                                ; next digit

r11d ist der Akkumulator, und er ist 32 Bit breit. Jede Ziffer führt value <<= 4; value += digit aus. Kein Ziffernzähler, keine Größenbegrenzung, keine Überlaufprüfung, kein jo irgendwo in der Schleife. Die neunte Ziffer führt nicht zu einem Fehler; sie verschiebt den oberen Teil der Zahl über das Ende des Registers hinaus, und niemand bemerkt es. 0x100000005 & 0xffffffff = 5, und der Parser ist damit vollkommen zufrieden.

Die einzige Plausibilitätsprüfung weist die falsche Hälfte zurück

Es gibt genau eine nachgelagerte Plausibilitätsprüfung, und sie ist auf fast poetische Weise falsch. Der Dechunking-Treiber (sub_20af6b0, Aufrufstellen 0x20af719 / 0x20af9fb, Größe gespeichert unter [r12+0x344]) wendet einen Vorzeichentest auf den akkumulierten Wert an. Man halte das einen Moment fest: Die einzigen Wraps, die erkannt werden, sind diejenigen, die in der negativen Hälfte landen, [0x80000000, 0xffffffff]. Eine umgelaufene Größe, deren untere 32 Bit unter 0x80000000 liegen, kommt als völlig normale Chunk-Größe durch. 0x100000005, das zu 5 umläuft, ist der kanonische Fall: umgelaufen, unbemerkt und verheerend.


Warum es schmuggelt

Das Paket wird aufgrund einer einzigen Designentscheidung in der Art und Weise, wie NetScaler Bodies behandelt, zu einem Schmuggel: Es leitet die Chunked-Framing des Clients Byte für Byte unverändert an das Backend weiter, während es sein eigenes (umgelaufenes) Verständnis dieses Framings nutzt, um zu entscheiden, wo die Anfrage des Clients endet.

So beendet NetScaler Anfrage #1 nach fünf Body-Bytes und stellt die nachfolgenden 37 als zweite, gepipelinetе Anfrage in die Warteschlange. Das Backend, das die Arithmetik korrekt durchführt, liest 100000005 als 4.294.967.301 und wartet weiter auf den Body von Anfrage #1. Von diesem Punkt an lesen beide Boxen denselben Stream und leben in unterschiedlichen Welten.

In welcher Welt man landet, hängt vom Backend ab.

Flow A: korrektes 64-Bit-Backend. Die Desync-Klemme.

Attacker                           NetScaler (<=73.30)                            Backend (RFC 64-bit)
   |                                        |                                               |
   |  [1] one TCP segment, 122 bytes:       |                                               |
   |    POST /wrap HTTP/1.1                 |                                               |
   |    Host: poc                           |                                               |
   |    Transfer-Encoding: chunked          |                                               |
   |    100000005\r\nAAAAA\r\n0\r\n\r\n     |                                               |
   |    GET /SMUGGLED HTTP/1.1              |                                               |
   |    Host: poc\r\n\r\n                   |                                               |
   |--[1]---------------------------------->|                                               |
   |                                        | [2] parses "100000005" into a u32             |
   |                                        |     wraps to 5; consumes AAAAA;               |
   |                                        |     sees terminating 0-chunk                  |
   |                                        |     ==> request #1 COMPLETE                   |
   |                                        |     trailing 37 bytes held as a               |
   |                                        |     pending pipelined request #2              |
   |                                        |                                               |
   |                                        |--[3] 85 bytes, framing VERBATIM-------------->|
   |                                        |   POST /wrap HTTP/1.1                         |
   |                                        |   Transfer-Encoding: chunked                  |
   |                                        |   100000005\r\nAAAAA\r\n0\r\n\r\n             |
   |                                        |                                               |
   |                                        |                                               | [4] parses 0x100000005 (64-bit)
   |                                        |                                               |     = 4,294,967,301 bytes
   |                                        |                                               |     waiting for a body that never co
   |                                        |                                               |     [WEDGED: no response, ever]
   |                                        |                                               |
   |                                        | GET /SMUGGLED waits in NetScaler's            |
   |                                        | pipeline queue forever: response #1           |
   |                                        | never arrives                                 |
   |                                        |                                               |

Ablauf B: Backend, das wie NetScaler auf 32 Bit kürzt. Der vollendete Smuggle.

Tool herunterladen