本文原創(chuàng)作者:adlab_mickey
來源:安全客
漏洞發(fā)現(xiàn)人:Philip Pettersson
漏洞編號(hào):CVE-2016-8655
漏洞危害:高危,低權(quán)限用戶利用該漏洞可以在Linux系統(tǒng)上實(shí)現(xiàn)本地提權(quán)。
影響范圍:Linux內(nèi)核(2011年4月19日發(fā)行)開始就受影響了,直到2016年11月30日修復(fù)。
漏洞描述
Philip Pettersson在Linux (net/packet/af_packet.c)發(fā)現(xiàn)條件競爭漏洞,可以通過內(nèi)核代碼進(jìn)行權(quán)限提升。
這個(gè)bug最早出現(xiàn)于2011年4月19號(hào)的代碼中,詳細(xì)請(qǐng)參考:
https://github.com/torvalds/linux/commit/f6fb8f100b807378fda19e83e5ac6828b638603a
它于2016年11月30號(hào)被修復(fù),詳細(xì)請(qǐng)參考:
漏洞細(xì)節(jié)
新建AF_PACKE套接字你需要CAP_NET_RAW在你的網(wǎng)絡(luò)命名空間?,然而系統(tǒng)中非權(quán)限的進(jìn)程在非權(quán)限的命名空間可以獲得這個(gè)能力(Ubuntu,?Fedora等發(fā)行版),這個(gè)漏洞可以在容器內(nèi)觸發(fā),從而入侵整個(gè)主機(jī)內(nèi)核。在android上,有?gid=3004/AID_NET_RAW的進(jìn)程可以新建AF_PACKET套接字?(mediaserver),從而觸發(fā)這個(gè)漏洞。
問題出在inside packet_set_ring() 和 packet_setsockopt()函數(shù)中,我們可以看到當(dāng)套接字使用PACKET_RX_RING選項(xiàng)時(shí)候,packet_set_ring()會(huì)調(diào)用setsockopt()函數(shù)。
如果套接字的版本是TPACKET_V3,一個(gè) timer_list對(duì)象將會(huì)在init_prb_bdqc()調(diào)用時(shí)被 packet_set_ring()初始化。
1
2
3
4
5
6
7
8
9
10
11
|
switch ?(po->tp_version)?{ ???????????????? case ?TPACKET_V3: ???????????????? /*?Transmit?path?is?not?supported.?We?checked ????????????????? *?it?above?but?just?being?paranoid ????????????????? */ ???????????????????????? if ?(!tx_ring) ???????????????????????????????? init_prb_bdqc(po,?rb,?pg_vec,?req_u); ???????????????????????? break ; ???????????????? default : ???????????????????????? break ; ???????????????? } |
函數(shù)的流程如下:
1
|
packet_set_ring()->init_prb_bdqc()->prb_setup_retire_blk_timer()->prb_init_blk_timer()->prb_init_blk_timer()->init_timer() |
當(dāng)套接字關(guān)閉,packet_set_ring()會(huì)再次被調(diào)用,如果packet的版本> TPACKET_V2,會(huì)釋放和刪除先前初始化的定時(shí)器。
1
2
3
4
5
|
? if ?(closing?&&?(po->tp_version?>?TPACKET_V2))?{ ???????????????? /*?Because?we?don't?support?block-based?V3?on?tx-ring?*/ ???????????????? if ?(!tx_ring) ???????????????????????? prb_shutdown_retire_blk_timer(po,?rb_queue); ???????? } |
當(dāng)packet版本為TPACKET_V1時(shí),init_prb_bdqc()將會(huì)在packet_setsockopt()后被執(zhí)行,在packet_set_ring() 函數(shù)前返回。
ring buffer被初始化后,可以嘗試拒絕改變套接字版本。但是這樣的校驗(yàn)是不完整的。
1
2
3
4
5
|
case ?PACKET_VERSION: ???????? { ... ?????????? if ?(po->rx_ring.pg_vec?||?po->tx_ring.pg_vec) ?????????????????? return ?-EBUSY; |
在 packet_set_ring()中init_prb_bdqc() 和 ?swap(rb->pg_vec, pg_vec) 之間的調(diào)用有足夠的空間來競爭這條代碼路徑
當(dāng)套接字關(guān)閉,packet_set_ring()將不會(huì)刪除定時(shí)器,因此這時(shí)套接字的版本為TPACKET_V1,timer_list 結(jié)構(gòu)體描述定時(shí)器對(duì)象定位在內(nèi)部的packet_sock結(jié)構(gòu)體中,套接字將調(diào)用kfree()釋放。
我們可以在通過UAF利用定時(shí)器對(duì)象上對(duì)SLAB分配器實(shí)現(xiàn)不同的中毒攻擊(我發(fā)現(xiàn)add_key()是最可靠的),這最終會(huì)導(dǎo)致當(dāng)定時(shí)器過期內(nèi)核跳到處理函數(shù)。
通過在packet_setsockopt()中使用lock_sock(sk)來修復(fù)這個(gè)bug,同時(shí)鎖定packet版本。
漏洞驗(yàn)證
稍后更新
POC
稍后更新
相關(guān)鏈接
http://seclists.org/oss-sec/2016/q4/607
http://malwarejake.blogspot.com/2016/12/new-linux-privilege-escalation.html
https://security-tracker.debian.org/tracker/CVE-2016-8655
https://github.com/torvalds/linux/commit/f6fb8f100b807378fda19e83e5ac6828b638603a
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-8655
https://www.ubuntu.com/usn/usn-3151-1/
原文地址:http://bobao.#/learning/detail/3267.html