Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

フィードお問い合わせプライバシー© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-88776 — CVE-2026-88776の技術解説。NetScaler nsppeのOracle TNSレコードパーサーにおける認証前の整数アンダーフローにより、境界外書き込みとパケットエンジンのクラッシュを引き起こす。 | Kitploit
ツール/GitHubGitHub/scyrix-llc/cve-2026-88776
メモリフォレンジック脆弱性分析エクスプロイトリバースエンジニアリングネットワークセキュリティバイナリ解析論文と研究
GitHubscyrix-llc/cve-2026-88776

CVE-2026-88776

CVE-2026-88776の技術解説。NetScaler nsppeのOracle TNSレコードパーサーにおける認証前の整数アンダーフローにより、境界外書き込みとパケットエンジンのクラッシュを引き起こす。

リポジトリを見る
21328日前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

CVE-2026-88776: NetScaler nsppe (認証前OOB書き込み)

DataStream / Oracle TNSレコードパーサーにおける整数アンダーフロー

概要

NetScalerはOracleデータベースをロードバランシングできる。ORACLEタイプのvserverを向けると、パケットエンジンはOracle TNSプロトコル自体を話し始め、組み込みハンドラでクライアントトラフィックを解析する。そのハンドラは接続ごとに小さなステートマシンを保持し、TNSレコード内のどこにいるかを記憶する。

その状態の1つは「レコードの途中で、さらにバイトが来る」という意味を持つ。次のセグメントが到着すると、ハンドラはその長さを読み取り、10を引く。なぜなら各セグメントの10バイトはヘッダーだからだ。

セグメントが10バイトより短い場合に何が起こるかを、誰も問いかけなかった。

1つ送ってみよう。1〜9バイトの小さなセグメントがその状態に入り、長さが負になるが、長さは符号なし16ビットレジスタに格納されているため負にはならない。それは巨大な値、最大で約64 KBにラップアラウンドする。そしてハンドラはその量のデータをあなたのパケットから.bss内の固定0x748バイトのスクラッチバッファへ意気揚々とmemcpyする。エンジンはPIEではないため、踏みつけられるアドレスは決して移動しない。

ログインする必要はない。vserverの背後にデータベースすら必要ない。アプライアンスがTNSハンドシェイク自体に応答するからだ。攻撃全体は1つのTCP会話で完結する。

両方の側面がライブで実演された:

  • ラップされた長さを発射すると、パケットエンジンはSIGSEGVで死に、アプライアンスのデータプレーンを約1分間ダウンさせる。決定的で、再現可能で、ループ可能。
  • 長さを調整すれば静かなバージョンになる。攻撃者のバイトがスクラッチバッファの隣にあるグローバル変数の上に着地し、エンジンは動き続ける。これは単なるクラッシュではなく、書き込みプリミティブだ。

根本原因

ステートマシンと、その操り方

ハンドラは接続ごとの状態を[pcb+0x15a]に格納する。ほとんどの状態は退屈だ。ここで重要なのは0x1F4で、「レコード途中、継続待ち」を意味し、通常のプロトコルバイトだけで接続をその状態へ誘導できる:

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

その接続上の次のパケットは 0x1F4 でディスパッチされ、bd49a7 を経由して bd5362 に入り、ここに到達します:

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

文のように読んでください。セグメントの長さを取得します。10を引きます。結果を保存し、memcpyに渡して完了です。どこにも「長さマイナス10」がまだ意味のある数値かどうかを問い合わせる箇所はありません。

存在しないガード

この関数内でその長さフィールドへの参照をすべて数えました。30箇所あります。チェックはちょうど1つだけ、bd4083 にあり、それはゼロとの比較を行うだけです。長さゼロのセグメントは拒否されます。それ以外の長さ、1から9を含め、すべてがそのまま減算へと進みます。

コードは、ステート 0x1F4 が実行される時点でステートマシンが十分に完全なレコードを渡していると明確に信じています。ステートマシンはそのようなことを一切約束していません。単独のパケットとして到着する小さすぎるセグメントは、すべてのディスパッチ条件を満たし、5バイト不足した状態で現れます。

本当に腹立たしいのは、ベンダーがこのバグクラスを認識していることです。まったく同じバイナリの別の場所では、sub_119c940 が同一の長さマイナス定数の算術を行い、cmp eax,0x3f9 / ja でそれをゲートしています。安全なパターンはすぐそこにありました。この箇所ではただそれを使っていなかっただけです。

ラップしたときに何が起きるか

宛先 0x30a8075 は 0x748 バイトのスクラッチ領域内にあり、その手前には正当な空間が 0x533 バイトしかありません。ラップしたコピーはそれを越えて隣接する DataStream およびネゴシエーションのグローバルへ、あなたのバイト列で溢れ出します。そしてラップした長さ自体が 0x30a8476 に永続化され、後のコードがそれを読み戻して信頼します。これは memcpy から一段離れた、第二の破壊経路です。


トリガー

セットアップは1行の設定、標準的な DataStream デプロイメントです:

add lb vserver v ORACLE <ip> 1521

バックエンドは不要です。アプライアンスはTNS自体を終端し、独自のAcceptパケットを構築します。「Netscaler」ベンダー文字列も含めてすべてです。

会話は4つのステップで進行します:

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

ステップ1から3は純粋な会話です。ステップ4は5バイトです。


観測されたクラッシュ挙動

これは14.1-73.30アプライアンス上で2回実行されており、同じマシン、同じビルドで、2回の独立した実行です。どちらの場合もパケットエンジンがSIGSEGVで落ち、一致するコアダンプが生成され、ns.logにはその時間枠内でシグナル11が記録され、データプレーンは約60秒間のウォームリスタートの間停止しました。

ネガティブコントロールは両方の実行で合格しました。同一の会話を実行しつつ、最終セグメントを整合性のある10バイトにすると、何も起こりません。エンジンはそれを処理してそのまま動作を続けます。問題となるのは、この中途半端な長さだけです。

ツールをダウンロード