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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
regreSSHion — これはCVE-2024-6387用に書いたPOCです。 | Kitploit
ツール/GitHubGitHub/teamos-hub/regresshion
脆弱性分析エクスプロイトペネトレーションテストレッドチーミングリモートアクセスツールバイナリエクスプロイト
GitHubteamos-hub/regresshion

regreSSHion

これはCVE-2024-6387用に書いたPOCです。

リポジトリを見る
192年前未レビュー

人気

すべて見る →

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

すべてのツールを探索

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

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

Qualys Security Advisory

regreSSHion: OpenSSHサーバーにおけるRCE、glibcベースのLinuxシステム上 (CVE-2024-6387)

===================================================================== 目次

概要 SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3 (Debian 3.0r6, 2005年)

  • 理論
  • 実践
  • タイミング SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3 (Ubuntu 6.06.1, 2006年)
  • 理論、その1
  • 理論、その2
  • 実践
  • タイミング SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2 (Debian 12.5.0, 2024年)
  • 理論
  • 実践
  • タイミング amd64エクスプロイトに向けて パッチと軽減策 謝辞 タイムライン

===================================================================== 概要

必要なのは信仰の跳躍だけ
    -- The Interrupters, "Leap of Faith"

予備的注記: OpenSSHは世界で最も安全なソフトウェアの一つです。この脆弱性は、ほぼ完璧な実装における一度のミスです。その多層防御設計とコードは模範であり、インスピレーションを与えるものであり、OpenSSHの開発者の模範的な仕事に感謝します。

私たちはOpenSSHサーバー(sshd)において、シグナルハンドラの競合状態の脆弱性(CVE-2024-6387)を発見しました。クライアントがLoginGraceTime秒(デフォルト120秒、古いOpenSSHバージョンでは600秒)以内に認証しない場合、sshdのSIGALRMハンドラが非同期に呼び出されます。しかし、このシグナルハンドラは非同期シグナルセーフではないさまざまな関数(例: syslog())を呼び出します。この競合状態は、sshdのデフォルト設定に影響します。

調査の結果、この脆弱性は実際には2006年にMark Dowd氏によって報告されたCVE-2006-5051(「OpenSSH 4.4以前のシグナルハンドラ競合状態により、リモート攻撃者がサービス拒否(クラッシュ)を引き起こし、任意のコードを実行する可能性がある」)の回帰であることがわかりました。

この回帰は2020年10月(OpenSSH 8.5p1)に、コミット752250c(「OpenSSHのための改訂されたログ基盤」)によって導入されました。このコミットは、sshdのSIGALRMハンドラから直接呼び出される関数sigdie()から"#ifdef DO_LOG_SAFE_IN_SIGHAND"を誤って削除しました。言い換えれば:

  • OpenSSH < 4.4p1は、CVE-2006-5051に対するバックポートパッチが適用されていない場合、またはCVE-2006-5051に対する不正確な修正であるCVE-2008-4109に対するパッチが適用されていない場合、このシグナルハンドラ競合状態の影響を受けます。
  • 4.4p1 <= OpenSSH < 8.5p1は、このシグナルハンドラ競合状態の影響を受けません(CVE-2006-5051のパッチでsigdie()に追加された"#ifdef DO_LOG_SAFE_IN_SIGHAND"によって、この安全でない関数が安全な_exit(1)呼び出しに変換されたため)。
  • 8.5p1 <= OpenSSH < 9.8p1は、再びこのシグナルハンドラ競合状態の影響を受けます("#ifdef DO_LOG_SAFE_IN_SIGHAND"がsigdie()から誤って削除されたため)。

この脆弱性はglibcベースのLinuxシステム上でリモートから悪用可能であり、syslog()自体が非同期シグナルセーフでない関数(例: malloc()やfree())を呼び出します。これは認証されていないリモートコード実行をroot権限で引き起こします。sshdの特権コードに影響し、サンドボックス化されておらず、完全な権限で実行されるためです。私たちは他のlibcやオペレーティングシステムについては調査していません。ただし、OpenBSDは明らかに影響を受けません。なぜなら、そのSIGALRMハンドラはsyslog_r()を呼び出しますが、これはOpenBSDが2001年に発明したasync-signal-safeなsyslog()のバージョンだからです。

この脆弱性をリモートから悪用するために(私たちの知る限り、CVE-2006-5051はこれまでに正常に悪用されたことはありません)、私たちは2001年にMichal Zalewski氏によって発表された先見性のある論文「Delivering Signals for Fun and Profit」からインスピレーションを得ました。

https://lcamtuf.coredump.cx/signals.txt

それでも、私たちは直ちに3つの主要な問題に直面しました。

  • 理論的な観点から、適切なタイミングでSIGALRMによって中断された場合にsshdを矛盾した状態にする有用なコードパスを見つけ、その後SIGALRMハンドラ内部でこの矛盾した状態を悪用する必要があります。
  • 実用的な観点から、sshd内のこの有用なコードパスに到達する方法を見つけ、適切なタイミングで中断する可能性を最大化する必要があります。
  • タイミングの観点から、リモートからこの有用なコードパスを適切なタイミングで中断する可能性をさらに高める方法を見つける必要があります。

これらの3つの問題に集中し、最新のオペレーティングシステムの保護機構(特にASLRとNX)にすぐに立ち向かわなくて済むように、まずi386上の古いOpenSSHバージョンをエクスプロイトし、その後その経験に基づいて最近のバージョンをエクスプロイトすることにしました。

  • 最初に、"SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3"("debian-30r6-dvd-i386-binary-1_NONUS.iso"から)を取り上げました。これは、デフォルトで権限分離が有効になっている最初のDebianバージョンであり、当時の重大な脆弱性(特にCVE-2003-0693とCVE-2002-0640)に対してパッチが適用されています。

    このバージョンをリモートから悪用するために、free()の呼び出しをSIGALRMで中断し(sshdの公開鍵解析コード内)、ヒープを矛盾した状態にし、SIGALRMハンドラ内の別のfree()呼び出し中にこの矛盾した状態を悪用します。

    実験では、この競合状態に勝つには平均で約10,000回の試行が必要でした。つまり、600秒(LoginGraceTime)あたり10接続(MaxStartups)が受け入れられる場合、リモートルートシェルを取得するには平均で約1週間かかります。

  • 2番目に、"SSH-2.0-OpenSSH_4.2p1 Debian-7ubuntu3"("ubuntu-6.06.1-server-i386.iso"から)を取り上げました。これは、CVE-2006-5051(「OpenSSH 4.4以前のシグナルハンドラ競合状態」)の影響を受ける最後のUbuntuバージョンです。

    このバージョンをリモートから悪用するために、pam_start()の呼び出しをSIGALRMで中断し、PAMの構造の1つを矛盾した状態にし、SIGALRMハンドラ内のpam_end()呼び出し中にこの矛盾した状態を悪用します。

    実験では、この競合状態に勝つには平均で約10,000回の試行が必要でした。つまり、120秒(LoginGraceTime)あたり10接続(MaxStartups)が受け入れられる場合、リモートルートシェルを取得するには平均で約1~2日かかります。

  • 最後に、"SSH-2.0-OpenSSH_9.2p1 Debian-2+deb12u2"("debian-12.5.0-i386-DVD-1.iso"から)を取り上げました。これは現在のDebian安定版であり、CVE-2006-5051の回帰の影響を受けます。

    このバージョンをリモートから悪用するために、malloc()の呼び出しをSIGALRMで中断し(sshdの公開鍵解析コード内)、ヒープを矛盾した状態にし、SIGALRMハンドラ内の別のmalloc()呼び出し中(より正確にはsyslog()内)にこの矛盾した状態を悪用します。

    実験では、この競合状態に勝つには平均で約10,000回の試行が必要でした。したがって、120秒(LoginGraceTime)あたり100接続(MaxStartups)が受け入れられる場合、約3~4時間です。最終的に、リモートルートシェルを取得するには平均で約6~8時間かかります。なぜなら、glibcのアドレスを正しく推測できるのは半分の時間だけだからです(ASLRのため)。

この研究はまだ進行中です。

  • 仮想マシンのみを対象としており、ベアメタルサーバーではない、ほぼ安定したネットワークリンク(約10msのパケットジッタ)での実験です。
  • エクスプロイトのさまざまな側面は大幅に改善できると確信しています。
  • amd64エクスプロイトの作業を開始しましたが、これはより強力なASLRのためにはるかに困難です。

amd64での作業を開始してから数日後、sshdのSIGALRMハンドラにおけるデッドロックに関する以下のバグレポート(OpenSSHの公開Bugzilla内)に気付きました。

https://bugzilla.mindrot.org/show_bug.cgi?id=3690

したがって、私たちはすぐにOpenSSHの開発者に連絡し(このデッドロックが悪用可能な脆弱性によって引き起こされていることを知らせるため)、amd64の作業を保留し、このアドバイザリの作成を開始しました。

===================================================================== SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3 (Debian 3.0r6, 2005年)


理論

しかし、それは私らしくない、私は解放されている
    -- The Interrupters, "Haven't Seen the Last of Me"

このOpenSSHバージョンのSIGALRMハンドラはpacket_close()を呼び出し、それはbuffer_free()を呼び出し、さらにxfree()、そしてfree()を呼び出します。free()はasync-signal-safeではありません。


302 grace_alarm_handler(int sig) 303 { ... 307 packet_close();

329 packet_close(void) 330 { ... 341 buffer_free(&input); 342 buffer_free(&output); 343 buffer_free(&outgoing_packet); 344 buffer_free(&incoming_packet);

35 buffer_free(Buffer *buffer) 36 { 37 memset(buffer->buf, 0, buffer->alloc); 38 xfree(buffer->buf); 39 }

51 xfree(void *ptr) 52 { 53 if (ptr == NULL) 54 fatal("xfree: NULL pointer given as argument"); 55 free(ptr); 56 }

そこで、このDebianのglibc(2.2.5)のmallocコードを調べ始めました。free()への最初の呼び出しがSIGALRMによって中断され、SIGALRMハンドラ内の2回目のfree()呼び出し(上記の341-344行)中に悪用される可能性があるかどうかを確認するためです。このglibcのmallocは、2000年にSolar Designer氏が先駆的に開発したunlink()テクニックに対して強化されていないため、chunk_free()(free()から内部的に呼び出される)の中にすぐに興味深いコードパスを見つけました。


1028 struct malloc_chunk 1029 { 1030 INTERNAL_SIZE_T prev_size; /* 前のチャンクのサイズ(解放されている場合) / 1031 INTERNAL_SIZE_T size; / オーバーヘッドを含むバイト単位のサイズ / 1032 struct malloc_chunk fd; /* 二重リンクリスト -- 解放されている場合のみ使用 / 1033 struct malloc_chunk bk; 1034 };

2516 #define unlink(P, BK, FD)
2517 {
2518 BK = P->bk;
2519 FD = P->fd;
2520 FD->bk = BK;
2521 BK->fd = FD;
2522 } \

3160 chunk_free(arena ar_ptr, mchunkptr p) .... 3164 { 3165 INTERNAL_SIZE_T hd = p->size; / ヘッドフィールド / .... 3177 sz = hd & ~PREV_INUSE; 3178 next = chunk_at_offset(p, sz); 3179 nextsz = chunksize(next); .... 3230 if (!(inuse_bit_at_offset(next, nextsz))) / 前方統合 / 3231 { .... 3241 unlink(next, bck, fwd); .... 3244 } 3245 else 3246 set_head(next, nextsz); / inuseビットをクリア */ .... 3251 frontlink(ar_ptr, p, sz, idx, bck, fwd);

このコードパスを悪用するために、sshdのヒープを以下のレイアウトに配置します(chunk_X、chunk_Y、chunk_Zはmalloc()されたメモリチャンクであり、p、s、f、bはそれぞれprev_size、size、fd、bkフィールドです)。

ツールをダウンロード