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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
cve-2026-98260-uaf — CVE-2026-98260(posix-cpu-timers exec UAF)エクスプロイト研究:S9280 Android 14 GKI 6.1 — UAFトリガー + ゼロ書き込みプリミティブ + SELinux Permissive。引き継ぎドキュメントはHANDOFF.mdにあります。 | Kitploit
ツール/GitHubGitHub/nanoturtle1145/cve-2026-98260-uaf
Androidセキュリティ特権昇格メモリフォレンジック脆弱性分析エクスプロイト論文と研究バイナリエクスプロイト
GitHubnanoturtle1145/cve-2026-98260-uaf

cve-2026-98260-uaf

CVE-2026-98260(posix-cpu-timers exec UAF)エクスプロイト研究:S9280 Android 14 GKI 6.1 — UAFトリガー + ゼロ書き込みプリミティブ + SELinux Permissive。引き継ぎドキュメントはHANDOFF.mdにあります。

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

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2026-98260 — トリガーのみのPoC(posix-cpu-timers UAF)

脆弱性

exec: Cleanup POSIX timers right after de_thread()(作者 Hyunwoo Kim、2026-09-11 アップストリーム、 Fixes: 55e8c8eb2c7b = 5.7 以降)。

非リーダースレッド E に CLOCK_THREAD_CPUTIME_ID タイマーが登録されている。execve() 内で de_thread() が tid を交換した後、タイマーは PID による task の逆引きに失敗し、ノードは E の posix_cputimers に残ったままになる。exec_mmap() の mmap_read_lock_killable() が -EINTR を返す場合(exec が失敗し、クリーンアップコードはさらに後方にある)、do_exit() → exit_itimers() が k_itimer を解放するがノードは取り除かれない。親プロセスの wait4() による回収時に cleanup_timerqueue() → timerqueue_del() が解放済みオブジェクトに対して操作を行い → UAF となる。

パッチ状態(2026-10-27 実測、各安定ブランチの fs/exec.c を確認)

ブランチposixtimer_exec状態
linux-6.1.yなし未修正
linux-5.15.yなし未修正
linux-6.6.yあり修正済み(6.6.158+)
linux-6.12.yあり修正済み(6.12.112+)

→ 本プロジェクトの対象(5.15 / 6.1 系、および 6.6.158 未満の 6.6)はすべて影響範囲内。

このトリガーが「確定的」でありタイミング頼みではない理由

  1. 長い書き込みロックのウィンドウ:fragment_vmas() は memfd + MAP_FIXED でアドレス空間を --vmas(デフォルト 50000)個のマージ不可 VMA に分割する(各 VMA の vm_pgoff はすべて 0 で、 隣接アドレスの pgoff が連続しない → vma_merge が失敗)。locker スレッドが全区間を繰り返し mprotect し、数万の VMA を走査することで mmap 書き込みロックがミリ秒単位で保持される。
  2. 正確な同期ポイント:killer は tgkill(tgid, 旧 tid, 0) が ESRCH を返すことで 「de_thread() の tid 交換が完了した」と判断し、その時点で初めて SIGKILL を送る。
  3. 被害スレッドは exec_mmap() の箇所で mmap_read_lock_killable() に必ずブロックし (読み取りロックが書き込みロックに阻まれる)、SIGKILL はその直後にマイクロ秒単位で到達する → この呼び出しは -EINTR を返す → exec が失敗する。ウィンドウ(ms)≫ 反応時間(µs)であるため、運に依存しない。

⚠️ 注意すべき区別:トリガーは確定的である。UAF から任意書き込み/cred 改変までは posix_timers_cache の slab 再利用の編成(order、objects/slab、CPU partial、 memcg の所属)に依存し、これは測定可能かつ反復可能なヒープエンジニアリングであり、競合状態ではない。

ビルド

export ANDROID_NDK_HOME=/home/nt/项目/samsung_root_research/06_工具链/android-ndk-r29
make            # 产物 trigger(aarch64 / Android 21+ / 仅依赖 libc、libdl)

テスト手順

adb push trigger /data/local/tmp/
adb shell "chmod 755 /data/local/tmp/trigger"
adb shell "/data/local/tmp/trigger --check"        # 先看环境
adb shell "/data/local/tmp/trigger; echo exit=\$?"

成功の目印(3つのうち1つで可):

  • [*] 開始トリガー を出力した後にデバイスが再起動/画面が黒くなる(panic_on_oops=1 のとき最も直接的)
  • プロセスがシグナルで kill される(exit=137/139)、かつその後もシステムが生きている
  • dmesg(root 必要)に cleanup_timerqueue / timerqueue_del / rb_erase / rb_next のコールスタックが現れる

失敗(未トリガー)の場合、プログラムは自ら --attempts 回リトライし、各ラウンドの wait4 結果を出力し、 最後にパラメータ調整のヒントを表示する:--vmas 120000 --lockers 4 --cpu 0。

既知の制限

  • トリガーが成功するとほぼ必ずデバイスが再起動する(これが「成功」の証拠)。テスト前に未保存の作業がないことを確認すること。
  • Samsung の panic_on_oops は 0 の可能性がある:この場合タスクは kill され、カーネルは破損した rbtree を抱えたまま動き続ける。 2〜3 回連続で実行し、後続の panic が現れるか観察することを推奨。
  • 本 PoC は権限昇格コードを含まない(reclaim を行わず、cred にも触れない)。到達可能性と決定性の検証のみに使用する。

参考

  • 上流パッチ https://github.com/torvalds/linux/commit/acb03d3881818581052924a9bbbe92b8741ed448
  • Honor MagicPad3 Pro 完全チェーン(6.12.38、uid-0 と KSU ブートを含む)https://github.com/woshigenm/CVE-2026-98260
  • vivo/iQOO 6.6.127 移植ノート(回収オーケストレーション、SLUB パラメータ)https://github.com/janewas/cve-2026-98260-vivo-gki-research

実測記録(SM-S9280 / e3q / 6.1.162 / Android 17 / セキュリティパッチ 2026-09-05)

テスト環境:S9280ZHU6EZIF、カーネル 6.1.162-android14-11-34343818-abS9280ZHU6EZIF (ビルド 2026-09-20)、未 root、shell ドメイン(uid 2000)、SELinux Enforcing。

結論:トリガーは確定的(タイミングに賭けない)

ラウンド観測意味
各ラウンド親プロセスの tgkill(child_tgid, etid, 0) が ESRCH を返すde_thread() が tid 交換を完了した
各ラウンド続いて kill(child_tgid, SIGKILL)、子プロセスの rc=-9exec が中止された(成功した exec の rc=0 ではない)
--no-killer 対照exec が armed から終了まで 277 ms(killer ありでは 287 ms)mmap 書き込みロックが確かに exec_mmap() の mmap_read_lock_killable() を妨げた

5/5 ラウンドすべてで「ESRCH → SIGKILL → exec 失敗」に命中し、exec が成功した例は一度もない。 これは de_thread 後に exec を中止させるウィンドウが制御可能かつ安定していることを証明する;ウィンドウは locker の mprotect(6 万 VMA、1 回 200〜700 ms)に由来し、親プロセスの反応は µs 級である。

踏んだ2つの重要な落とし穴(いずれもコード内で修正済み)

  1. killer は親プロセス側に置く必要がある:de_thread() は zap_other_threads() で同一プロセスの 他のスレッドをすべて殺すため、子プロセス内に書いた killer は de_thread の瞬間に自ら先に死に、 永遠に ESRCH を見られない(exec が毎回成功するという挙動になる)。
  2. reclaim のタイミング:SIGKILL 直後の spray は無効——その時点では子プロセスはまだ死んでおらず、 k_itimer はまだ RCU で解放されていない。正しい順序は waitid(WNOWAIT) でゾンビを待つ → RCU コールバックの解放を待つ → ページを奪う → 最後に wait4 で回収パスをトリガーする。

未完了:UAF を可視化する

現在「解放後もノードがキューに残る」段階は安定して達成しているが、wait4 時点の rb_erase で oops は起きていない——被害 slab ページがまだ我々の spray に奪われていないことを示す(posix_timers_cache の partial slab はまだキャッシュされており、ページは buddy に戻っていない)。これは exploit の回収オーケストレーションの問題であり、 競合状態の問題ではない。vivo ノートのやり方に従う必要がある:まず k_itimer 自身で slab を満杯/空にして ページ全体の返却を促し、次に order-0 のキャリア(AIO ring など)で split された半ページを正確に受け止める。

次のステップの提案:このマシンを基準とし、docs/08-reclaim-choreography.md(vivo ノート)の 考え方に従って定向回収を行う;または KASAN 付きの自前ビルドカーネルで UAF が実際に発生するか検証する。


完全チェーン移植の実現可能性(SM-S9280 / 6.1.162 実測ハードル)

公開チェーン(Honor uid0.c)は tracefs の kmem イベントに依存して2つの重要なことを行う:

用途Honor 611/6.12 用の本機(Samsung 6.1.162)
被害者の k_itimer アドレス V を特定(payload のページ内オフセットを計算)kmem:kmem_cache_allocイベントは存在するが、events/kmem/*/enable は 0644 root:root であり、shell からはenable できない(events/sched/*/enable は書き込み可能、kmem は不可)
order-1 slab ページが buddy に返却されたことを判定(正確なページ奪取タイミング)kmem:mm_page_free同上、存在するが enable できない
生の trace バッファを読み取るper_cpu/cpuN/trace_pipe_raw読み取り可能(-r--r----- root readtracefs)✓
KASLR slide各 trace イベントの static site可能:sched イベントは enable 可能、プロジェクトに同種の手法あり ✓

結論:公開されているチェーンはそのまま移植できない。不足しているのはカーネル機能(イベントはすべて存在する)ではなく、shell に kmem イベントの enable 権限がないことである。

実行可能な代替案(改造が必要)

  1. V は不要になる:payload をページ内位置非依存にする——8KB ページ内のすべての可能な object スロット(k*0x108 + 0x78 + 0x10)に対して target を一度ずつ書き込む。これにより、被害オブジェクトが slab のどのスロットに位置しても、rb_erase は target に到達する。これは「全スロットカバー」で kmem_cache_alloc によるアドレス発見を置き換えることに等しい。
  2. ページ奪取をヒューリスティックに変更:mm_page_free による正確な同期を外した後は、RCU グレースピリオド後に 大量の sk_buff データページ(AF_UNIX SO_SNDBUF)を spray して、返却されたばかりの order-1 ページに ぶつけるしかなく、成功率は低下するため、precheck + リトライループが必要になる。
  3. KASLR slide:利用可能な sched イベントで行う(プロジェクトには既に SLIDE_TRACEFS_* 機構がある)。
  4. 最大のギャップ:cred アドレスをどこから得るか。公開チェーンは同じ kmem リークで cred を取得するが、 本機では不可能。選択肢:
    • 本プロジェクトに既存の KernelSnitch / pipe-page リークエンジンを再利用する(作業量は大きいが既存);
    • または、まずゼロ書きプリミティブで静的アドレス(例:selinux_state.enforcing、slide は既知)を攻撃する。 ただしそれでは SELinux を無効化できるだけで、uid 0 は取得できない。

結論:完全なチェーン = 数日規模の移植(まず位置非依存のページ奪取で UAF を可視化し、次に cred リークを解決する)であり、 一巡で通せるものではない。


研究進捗(2026-11-01 時点)

デバイス:SM-S9280 / 6.1.162-android14-11-34343818-abS9280ZHU6EZIF(One UI 9.0 / Android 17) ルート:UAF → ゼロ書きプリミティブ → cred ゼロ書き → uid 0。三つの段階で推進中、現在は第二段階で停滞。

概要

段階目標状態
一、トリガーposix-cpu-timers UAF を確実に発生させる✅ 実機で確認
二、UAF の可視化/制御解放済みオブジェクトを我々が制御する(キャリアによるページ奪取 or 同一 slab の再利用)✅ ページ奪取は実機で成立(P10:victim ページが buddy に返却され、こちらが受け止めた);⚠ タイミング要修正:キャリアの着地は reap より前でなければならない
三、権限昇格ゼロ書きで cred を改変 → uid 0🔶 チェーンは構築済み、実機では未達成

一、トリガー:確実に成立 ✅

de_thread() 後の exec 失敗 → exit_itimers() が k_itimer を解放するが rbtree ノードは摘除されない → 親プロセスの reap 時に timerqueue_del() が解放済みオブジェクトを操作する。実機の panic スタックがその証拠である:

pc : rb_next+0x24/0x54        lr : timerqueue_del+0x38/0x74
Call trace: rb_next / posix_cpu_timers_exit+0x78 / release_task+0xec /
            wait_consider_task+0x65c / do_wait / kernel_wait4 / __arm64_sys_wait4

2 つの重要な実装ポイント(いずれもコード内に反映済み):

  1. locker は clone(CLONE_VM|SIGCHLD) の独立プロセスでなければならず、pthread は使えない —— zap_other_threads() は同じ thread group しか殺さないため、pthread locker は de_thread() の冒頭で死に、 書き込みロックが解放される → exec が成功する → UAF は発生しない。
  2. 順序:exec スレッドの pthread_create と locker スタックの mmap は、lockers が書き込みロックを獲得する前に完了していなければならない。

二、UAF → 可視化:ページ奪取は実機で成立 ✅(次の障害はタイミング)

ツールをダウンロード