关联漏洞
介绍
# CVE-2023-20938
## 漏洞分析
1. client A与client B通过上下文管理器servicemanager建立Binder连接
2. A创建node 0xbeef([node = binder_new_node(proc, fp);](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=2410;drc=0988732d226d0ebcc5bf88e50c2a58ccad4c7cff?q=binder_transaction&ss=android%2Fkernel%2Fsuperproject)),B通过ref->target_node引用[node 0xbeef](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=3290;drc=f6baf87e49e3d65ab92e7a7964c611f2ba11cbb0?q=binder_transaction&ss=android%2Fkernel%2Fsuperproject)
3. B先正确处理target_node 0xbeef,将引用了target_node 0xbeef的事物binder_transaction存入A的事物队列([binder_enqueue_work_ilocked(&t->work, &proc->todo);](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=3063;drc=0988732d226d0ebcc5bf88e50c2a58ccad4c7cff?q=binder_transaction&ss=android%2Fkernel%2Fsuperproject)),使A可以再次引用被释放的悬挂指针
4. B使用未对其的offsets_size进入错误处理代码([IS_ALIGNED(tr->offsets_size, sizeof(binder_size_t))](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=3565;drc=f6baf87e49e3d65ab92e7a7964c611f2ba11cbb0?q=binder_transaction&ss=android%2Fkernel%2Fsuperproject)),导致还是0的buffer_offset被传入[binder_transaction_buffer_release](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=3964;drc=f6baf87e49e3d65ab92e7a7964c611f2ba11cbb0?q=binder_transaction&ss=android%2Fkernel%2Fsuperproject)函数从而触发漏洞
5. binder_transaction_buffer_release函数通过binder_dec_node调用[binder_dec_node_nilocked](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=1061;drc=4895725592c539226b2fe111b7577488b15187cf?q=binder_transaction&ss=android%2Fkernel%2Fsuperproject)函数,减少node 0xbeef的local_strong_refs引用计数器,但是node实例中有多个引用计数器及引用列表,只有当这些计数器都被清0时才会触发释放
6. 关闭B的binder触发[binder_cleanup_ref_olocked](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=1384;drc=4895725592c539226b2fe111b7577488b15187cf?q=binder_cleanup_ref&ss=android%2Fkernel%2Fsuperproject)函数,此时还会调用binder_dec_node_nilocked,当binder_dec_node_nilocked返回true时,将不会把指向node(0xbeef)的指针ref->node清空
7. 之后将会调用[binder_free_ref](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=6477;drc=4895725592c539226b2fe111b7577488b15187cf;bpv=1;bpt=1),在binder_free_ref函数中会将node 0xbeef[释放](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=1532;drc=4895725592c539226b2fe111b7577488b15187cf;bpv=1;bpt=1?q=binder_cleanup_ref&ss=android%2Fkernel%2Fsuperproject)
8. A将会在binder_thread_read函数中再次引用被释放的[node 0xbeef](https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/drivers/android/binder.c;l=5153;drc=4895725592c539226b2fe111b7577488b15187cf;bpv=1;bpt=1?q=binder_thread_read&ss=android%2Fkernel%2Fsuperproject)
额外说明:
真实android环境下普通应用权限无法通过servicemanager注册服务,但可以通过ITokenManager来实现两个进程的链接,本测试用例就是用了ITokenManager
## 说明
1. Makefile: make文件,可以修改里面的输出目录
2. 配置Cuttlefish模拟器
3. 编译内核环境,我触发漏洞的内核环境版本为:android12-5.10.136_r00,硬件架构使用x86_64
4. 在模拟器android中执行aapk,会看到如下kasan崩溃日志:
```[ 42.191535] poc (90) used greatest stack depth: 28232 bytes left
[ 43.177167] ==================================================================
[ 43.178189] BUG: KASAN: use-after-free in binder_ioctl+0x48de/0x50b0
[ 43.178438] Read of size 8 at addr ffff888116e99d58 by task poc/89
[ 43.178646]
[ 43.179102] CPU: 0 PID: 89 Comm: poc Not tainted 5.4.219 #1
[ 43.179309] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[ 43.179766] Call Trace:
[ 43.180332] dump_stack+0x76/0x9c
[ 43.180514] ? binder_ioctl+0x48de/0x50b0
[ 43.180738] print_address_description.constprop.0+0x16/0x200
[ 43.180962] ? binder_ioctl+0x48de/0x50b0
[ 43.181131] ? binder_ioctl+0x48de/0x50b0
[ 43.181303] __kasan_report.cold+0x1d/0x35
[ 43.181464] ? binder_ioctl+0x48de/0x50b0
[ 43.181626] kasan_report+0x10/0x20
[ 43.181761] binder_ioctl+0x48de/0x50b0
[ 43.181966] ? switch_mm_irqs_off+0x388/0xd80
[ 43.182127] ? __switch_to_asm+0x42/0x80
[ 43.182250] ? binder_thread_write+0x2070/0x2070
[ 43.182392] ? __schedule+0x71b/0x18b0
[ 43.182513] ? io_schedule_timeout+0x150/0x150
[ 43.182660] ? hrtimer_start_range_ns+0x635/0xc10
[ 43.182803] ? wait_woken+0x1c0/0x1c0
[ 43.182944] ? hrtimer_try_to_cancel+0x19/0x3f0
[ 43.183092] ? do_nanosleep+0x246/0x4c0
[ 43.183218] ? schedule_timeout_idle+0x50/0x50
[ 43.183363] ? _raw_spin_unlock_irqrestore+0x36/0x70
[ 43.183519] ? memset+0x20/0x40
[ 43.183632] do_vfs_ioctl+0x91e/0xef0
[ 43.183759] ? selinux_file_ioctl+0x36f/0x510
[ 43.183896] ? ioctl_preallocate+0x1a0/0x1a0
[ 43.184034] ? selinux_bprm_set_creds+0xcb0/0xcb0
[ 43.184182] ? memset+0x20/0x40
[ 43.184289] ? __rseq_handle_notify_resume+0x61d/0xb10
[ 43.184458] ? __x64_sys_rseq+0x4f0/0x4f0
[ 43.184600] ? security_file_ioctl+0x4b/0x90
[ 43.184742] ksys_ioctl+0x59/0x90
[ 43.184853] ? switch_fpu_return+0xc2/0x210
[ 43.184987] __x64_sys_ioctl+0x69/0xa0
[ 43.185112] ? prepare_exit_to_usermode+0x231/0x2c0
[ 43.185260] do_syscall_64+0x87/0x140
[ 43.185384] entry_SYSCALL_64_after_hwframe+0x5c/0xc1
[ 43.185665]
[ 43.185836] Allocated by task 89:
[ 43.186060] save_stack+0x1b/0x80
[ 43.186211] __kasan_kmalloc.constprop.0+0xc2/0xd0
[ 43.186380] binder_new_node+0x49/0x870
[ 43.186519] binder_transaction+0x4002/0x5d20
[ 43.186669] binder_thread_write+0x454/0x2070
[ 43.186816] binder_ioctl+0xff9/0x50b0
[ 43.186950] do_vfs_ioctl+0x91e/0xef0
[ 43.187070] ksys_ioctl+0x59/0x90
[ 43.187177] __x64_sys_ioctl+0x69/0xa0
[ 43.187296] do_syscall_64+0x87/0x140
[ 43.187419] entry_SYSCALL_64_after_hwframe+0x5c/0xc1
[ 43.187628]
[ 43.187760] Freed by task 67:
[ 43.187921] save_stack+0x1b/0x80
[ 43.188082] __kasan_slab_free+0x12e/0x170
[ 43.188286] kfree+0x90/0x250
[ 43.188485] binder_deferred_func+0xba6/0x1040
[ 43.188777] process_one_work+0x6fe/0x1250
[ 43.188989] worker_thread+0x534/0x1200
[ 43.189156] kthread+0x314/0x3e0
[ 43.189278] ret_from_fork+0x35/0x40
[ 43.189412]
[ 43.189509] The buggy address belongs to the object at ffff888116e99d00
[ 43.189509] which belongs to the cache kmalloc-128 of size 128
[ 43.190587] The buggy address is located 88 bytes inside of
[ 43.190587] 128-byte region [ffff888116e99d00, ffff888116e99d80)
[ 43.191116] The buggy address belongs to the page:
[ 43.191529] page:ffffea00045ba640 refcount:1 mapcount:0 mapping:ffff88811a801480 index:0x0
[ 43.192177] flags: 0x200000000000200(slab)
[ 43.192678] raw: 0200000000000200 dead000000000100 dead000000000122 ffff88811a801480
[ 43.192969] raw: 0000000000000000 0000000000100010 00000001ffffffff 0000000000000000
[ 43.193251] page dumped because: kasan: bad access detected
[ 43.193438]
[ 43.193518] Memory state around the buggy address:
[ 43.193928] ffff888116e99c00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 43.194205] ffff888116e99c80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 43.194434] >ffff888116e99d00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 43.194728] ^
[ 43.194976] ffff888116e99d80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 43.195291] ffff888116e99e00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 43.195653] ==================================================================
[ 43.196033] Disabling lock debugging due to kernel taint
[ 43.197301] binder: release 89:89 transaction 12 in, still active
[ 43.197576] binder: release 89:89 transaction 9 out, still active
[ 43.198094] binder: send failed reply for transaction 12, target dead
[ 43.198392] binder: send failed reply for transaction 9, target dead
```
TODO: exploit编写中...
文件快照
[4.0K] /data/pocs/446e06a4e676d9a882a5f1fb9758cccac5a90805
├── [1.8K] base.h
├── [8.5K] binder.c
├── [6.5K] binder.h
├── [ 15K] hwbinder.c
├── [1.5K] hwbinder.h
├── [ 310] Makefile
├── [4.7K] poc.c
├── [8.5K] README.md
├── [ 17K] uapi_binder.h
├── [4.4K] utils.c
└── [ 479] utils.h
0 directories, 11 files
备注
1. 建议优先通过来源进行访问。
2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。