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

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
CVE-2026-98937 — Linux perf/core の権限チェックバイパスに関する検証済みの PoC と分析。この脆弱性により、非特権の Android タスクにカーネルのコールチェーンアドレスが漏洩し、KASLR スライドの導出が可能になります。 | Kitploit
ツール/GitHubGitHub/woshigenm/cve-2026-98937
Androidセキュリティ特権昇格脆弱性分析エクスプロイト情報収集論文と研究
GitHubwoshigenm/cve-2026-98937

CVE-2026-98937

Linux perf/core の権限チェックバイパスに関する検証済みの PoC と分析。この脆弱性により、非特権の Android タスクにカーネルのコールチェーンアドレスが漏洩し、KASLR スライドの導出が可能になります。

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

人気

すべて見る →

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

すべてのツールを探索

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

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

CVE-2026-98937 — perf カーネルコールチェーンの権限バイパス

English | 简体中文

Linux perf/core の権限チェックバイパス: 非特権タスクが exclude_kernel=1 を設定したままカーネルコールチェーンを要求でき、perf_allow_kernel() ゲートを回避して perf リングバッファ経由でカーネルスタックフレームを漏洩させることができます。このリポジトリには分析と検証済みの PoC が含まれています。このバグは情報漏洩を引き起こすものであり、直接的な権限昇格プリミティブではありません。

ステータス

項目値
CVECVE-2026-98937
分類権限バイパス / 情報漏洩 (CWE-284/CWE-269)
対象Android arm64 (HONOR YLP-W00 および Redmi K70 で検証済み)
カーネルYLP-W00: 6.12.38-android16-5-gfde7767f6ef6-abogki481467632-4k; K70: 5.15.178-android13-8-00021-g6f2f96be86b9-ab13729987
SELinuxEnforcing (u:r:shell:s0)
パッチ適用なし; アップストリームでは 6.12.113 / 6.18.56 / 7.2.10 / 7.3+ で修正済み
ステータスPoC 検証済み; KASLR スライドオラクルは 6.12.38 および 5.15.178 で検証済み
事前チェックsrc/vuln_precheck.h

影響を受けるバージョン

以下の修正より前のカーネルが影響を受けます。a4b016d0a29038a5b7c96bf62c054bf7832451d9 ("perf/core: Check kernel access when kernel callchains are requested", Dapeng Mi、2026-06-30 マージ) および対応する安定版バックポートによって修正されています。

根本原因

perf_event_open() は以前、カーネルプロファイリングのゲートを !attr.exclude_kernel のみで行っていました:

if (!attr.exclude_kernel) {
        err = perf_allow_kernel(&attr);
        if (err)
                return err;
}

perf_allow_kernel() には perf_event_paranoid > 1 のチェックと SELinux の perf_event { kernel } フックの両方が含まれています。タスクは exclude_kernel=1 を設定しながら、カーネルコールチェーンを要求することができます(exclude_callchain_kernel=0 を指定した PERF_SAMPLE_CALLCHAIN)。その場合、perf_callchain() はサンプリングフィルタとは独立してカーネル部分を収集します。ユーザーモードのみをカウントするハードウェア PMU イベントは、カーネルコンテキストでオーバーフロー割り込みを発生させることがあるため(スキッド)、perf_callchain_kernel() はカーネルスタックをアンワインドし、カーネルテキストのアドレスをリングバッファに書き込みます。

修正では、カーネルサンプリングまたはカーネルコールチェーンのいずれかが要求された場合に perf_allow_kernel() を呼び出します:

if (!attr.exclude_kernel ||
    ((attr.sample_type & PERF_SAMPLE_CALLCHAIN) &&
     !attr.exclude_callchain_kernel)) {
        err = perf_allow_kernel();
        if (err)
                return err;
}

上記のスニペットは 6.12.113 安定ツリーの形式であり、そこでは perf_allow_kernel() が属性ポインタを受け取らなくなっています。アップストリームの コミットでは、同じ条件を perf_allow_kernel(&attr) で使用しています。

完全な呼び出しパス、skid の仕組み、SELinux 監査証跡、デバイスでの測定結果については docs/analysis.md を参照してください。

検証設計

PoC は非特権シェルプロセスとして 3 つのケースを実行します:

ケースperf_event 属性脆弱なカーネルでの期待結果
Aexclude_kernel=0EACCES(カーネル perf ゲートが有効)
Bexclude_kernel=1、exclude_callchain_kernel=1イベントは許可され、カーネルコールチェーンフレームはなし
Cexclude_kernel=1、exclude_callchain_kernel=0イベントは許可され、カーネルコールチェーンフレームが開示される

検証済みの YLP-W00(カーネル 6.12.38、SELinux Enforcing)では:

  • ケース A: EACCES、監査ログに avc: denied { kernel } ... tclass=perf_event が記録される。
  • ケース B: イベントはオープンされ、カーネルコールチェーンエントリは 0 件。
  • ケース C: イベントはオープンされ、カーネルコンテキストを持つ約 179k サンプルと、 約 537k のカーネルコールチェーンアドレス(サンプルあたり 3 フレーム)が得られ、 すべて 0xffffffde... のカーネル範囲に存在する。

検証済みの Redmi K70(カーネル 5.15.178、サードパーティ製 Android 17 ROM、 SELinux Enforcing)でも、同じパターンが観測されました:

  • ケース A: EACCES、同じ SELinux { kernel } 監査行。
  • ケース B: イベントはオープンされ、カーネルコールチェーンエントリは 0 件。
  • ケース C: イベントはオープンされ、period 1000 では 2,432 サンプル中 14,090 件、 period 5000 では 876 サンプル中 5,049 件のカーネルコールチェーンアドレスが 0xffffffdd... のカーネル範囲に存在する。

検証済みデバイスにおいて、修正済みカーネルではケース C が perf_event_open() の時点で EACCES により拒否されます。これはカーネルコールチェーンの 要求が perf_allow_kernel() に到達するようになったためです。

KASLR スライドの導出

一致する vmlinux があれば、漏洩したコールチェーンフレームは起動ごとの KASLR スライドオラクルになります。arm64 の仮想スライドは 2 MiB 単位で整列され、漏洩した すべてのテキストアドレスは _stext <= addr - slide < _etext を満たす必要があります。 これらの区間の交差を取ると、通常はちょうど 1 つのスライドが残ります。

make slide \
  SLIDE_VMLINUX=/path/to/vmlinux-6.12.38.elf \
  SLIDE_LINK_BASE=0xffffffc080000000 \
  SLIDE_LOG=logs/poc-ylp-w00-20261027-020133-period1000.log

検証済みのYLP-W00 6.12.38ブートでは、3つのフレームから一意にslide=0x1DCFC00000(実行時_text=0xffffffde4fc00000)が得られます:

リークされたアドレスリンク時アドレスシンボル
0xffffffde50748c780xffffffc080b48c78local_daif_restore+0x4 (msr DAIF, x0; ret)
0xffffffde50d406e00xffffffc0811406e0el0t_64_sync_handler+0x70 (bl el0_svcの後)
0xffffffde4fc115880xffffffc080011588el0t_64_sync+0x1a8 (bl el0t_64_sync_handlerの後)

これらはモジュールではなくコアカーネルのテキストフレームです。保留中のPMU割り込みは、システムコールエントリパス内のmsr DAIF, x0の後のretで正確に配送されます。KASLR下では生のアドレスを直接シンボル化することはできません。まずスライドを減算してください。フレームがモジュールアドレスの場合、すべてのアドレスを[_stext, _etext)に収めるスライドは存在せず、スクリプトは推測せずにその旨を報告します。スライドはブートごとに変化するため、再起動をまたいでキャッシュしてはなりません。

Redmi K70(5.15.178)も検証済みです。対応するイメージは/sdcard/boot.imgから取得され(boot v4、埋め込みバージョン文字列が実行中のカーネルと一致)、vmlinux-to-elfは158,668個のシンボルを復元しました。period-1000の1回の実行から得られた7つの一意なフレームによりslide=0x1D93800000(実行時_text=0xffffffdd9b800000)が得られ、syscall_trace_enter、el0_svc_common、do_el0_svc、el0_svc、el0t_64_sync_handler、el0t_64_sync、syscall_trace_exitに対応付けられます。

リンク時ベースはブランチ固有です — 5.15で6.12の値を再利用しないでください:

カーネルブランチKIMAGE_VADDR
Android 13-5.15 (K70)0xffffffc008000000
Android 16-6.12 (YLP-W00)0xffffffc080000000
upstream v5.15 (異なるレイアウト)0xffffffc010000000

vmlinux-to-elfはK70イメージに対して0xffffffc008000000を自動検出し、AOSP android13-5.15と一致しました。自動検出されたELFベースがブランチのKIMAGE_VADDRと異なる場合は、--link-base(またはSLIDE_LINK_BASE=)を渡してください。シンボル化はELF空間に留まり、報告されるスライドは真のベースに対して相対化され、実行時_textは定数ベースシフトに対して不変です。K70のリークを6.12.38イメージに与えることは意図的なネガティブテストのままであり、候補は得られません。

ビルド

要件:

  • /opt/android-ndk-r29にあるAndroid NDK r29(NDK=で上書き可能)
  • GNU make
  • adb
make                 # PoC, arm64, API 24
make ARCH=arm API=29 # other ABI / API level
make host            # static build for qemu-aarch64
make emu             # build and run the static PoC locally
make help

成果物は build/ に書き込まれ、git の管理対象外となります。

使用方法

make check                         # push + read-only environment pre-check
make run                           # push + full three-case verification

# directly
adb push build/poc /data/local/tmp/poc
adb shell chmod 755 /data/local/tmp/poc
adb shell /data/local/tmp/poc --check
adb shell /data/local/tmp/poc --duration 2 --period 1000

オプション:

--check         pre-check only, no perf event is opened
--force         run on an unlisted kernel release
--duration N    sampling seconds per case (default 2)
--period N      sample period in cycles (default 1000)

終了コード:

コード意味
0脆弱: ゲートがバイパスされ、カーネル呼び出しチェーンのフレームが観測された
2事前チェックで拒否 (不明なカーネルリリース、または環境ゲートの失敗)
3判定不能: イベントは開かれたが、カーネルフレームがサンプリングされなかった
4open 時に拒否 (修正済みまたは強制適用)
5バイパスすべきカーネル perf 制限が存在しない
6セットアップエラー (使用可能なハードウェア PMU イベントがない、予期しない errno)

--check を指定した場合、終了コード 0 はプロファイルゲートが続行されることを意味し、2 は拒否されることを意味します。perf イベントは開かれません。

PoC はハードウェアサンプリングデータを読み取るだけで、カーネル状態の書き込み、sysctl の変更、デバイスの再起動は行いません。

要件と制限事項

  • ハードウェア PMU イベント (cycles/instructions) が必要です。exclude_kernel=1 を指定したソフトウェアイベントはカーネルコンテキストでフィルタリングされ、skid パスに到達することはありません。
  • 検証済みなのは shell ドメイン (uid 2000) のみです。untrusted_app に perf_event { open } が許可されるかどうかはベンダーポリシーに依存します。このテスト用に APK はビルドされていません。
  • 検証済みの両デバイスでは kptr_restrict=2 のため、デバイス側でのシンボル化はできません。リークしたアドレスは、シンボル化ではなく範囲とカーネルコンテキストフラグによって検証されます。
  • PoC は perf_event_paranoid を変更しません。検証済みの両デバイスでは、実効的なゲートは SELinux です。スキップされる関数には paranoid チェックも含まれているため、perf_event_paranoid >= 2 の場合にも同じバイパスが適用されます。
  • K70 のカーネルは修正前にあたる 2025-07-02 にビルドされており、バックポートを含む正確な 5.15 安定版リリースは特定されていません。
  • スライドの導出には python3、nm、完全に一致する vmlinux、およびブランチの真の KIMAGE_VADDR が必要です。スライドは起動ごとに異なります。6.12.38 と 5.15.178 の両方が検証済みです。6.12.58 リリースはバージョンによって事前チェックプロファイルに含まれていますが、デバイス側の実行時検証はまだ保留中です。

リポジトリ構成

ツールをダウンロード