新聞中心
Linux內(nèi)核漏洞可能導(dǎo)致特權(quán)升級
作者 / 無憂主機(jī) 時(shí)間 2017-11-23 19:43:09
Andrey Konovalov最近披露了本地特權(quán)升級的漏洞,他在Linux網(wǎng)絡(luò)子系統(tǒng)內(nèi)部發(fā)現(xiàn)了漏洞,同時(shí)使用工具syzcaller“fuzzing”。在oss – sec的郵件線程中,Konovalov寫道:“當(dāng)構(gòu)建一個(gè)帶有MSG_MORE __ip_append_data()的UFO包時(shí),調(diào)用ip_ufo_append_data()來追加。然而,在兩個(gè)send()調(diào)用之間,append路徑可以從UFO切換到非UFO,這會(huì)導(dǎo)致內(nèi)存損壞。
NIC分流和UFOs
網(wǎng)絡(luò)接口卡(NIC)卸載允許協(xié)議棧傳輸大于以太網(wǎng)最大傳輸單元(MTU)的數(shù)據(jù)包,默認(rèn)情況下是1500字節(jié)。當(dāng)啟用NIC offload時(shí),內(nèi)核將把多個(gè)數(shù)據(jù)包組裝成一個(gè)大數(shù)據(jù)包,并將其傳遞給硬件,硬件處理IP碎片并將其分割成mtu大小的包。這種卸載經(jīng)常使用高速網(wǎng)絡(luò)接口來提高吞吐量,因?yàn)閁FO可以發(fā)送大型的UDP數(shù)據(jù)包。 Linux內(nèi)核可以利用各種NICs的分段卸載功能。引發(fā)POC
下面是一個(gè)簡單的概念證明 要在內(nèi)核中構(gòu)建UFO數(shù)據(jù)包,我們可以采取以下兩個(gè)步驟之一:使用UDP_CORK套接字選項(xiàng),該選項(xiàng)告訴內(nèi)核將此套接字上的所有數(shù)據(jù)累加到單個(gè)圖中,以在禁用該選項(xiàng)時(shí)傳輸; 調(diào)用send / sendto / sendmsg時(shí),使用MSG_MORE標(biāo)志,告訴內(nèi)核將此套接字上的所有數(shù)據(jù)累加到單個(gè)圖中,以便在未指定此標(biāo)志的調(diào)用時(shí)發(fā)送。此方法觸發(fā)此漏洞。在內(nèi)核中,udp_sendmsg函數(shù)負(fù)責(zé)構(gòu)造UDP數(shù)據(jù)包并將其發(fā)送到下一層。以下代碼顯示了在調(diào)用send / sendto / sendmsg時(shí),由用戶程序使用UDP_CORK套接字選項(xiàng)或MSG_MORE標(biāo)志啟用的UDP軟木塞功能的剝離實(shí)現(xiàn)。啟用UDP連接時(shí),會(huì)調(diào)用ip_append_data函數(shù)將多個(gè)數(shù)據(jù)包累積為單個(gè)大數(shù)據(jù)包。 函數(shù)ip_append_data是__ip_append_data的封裝,它負(fù)責(zé)管理套接字緩沖區(qū),方法是分配一個(gè)新的套接字緩沖區(qū)來存儲(chǔ)傳遞給它的數(shù)據(jù),或者在套接字被塞住時(shí)將數(shù)據(jù)附加到現(xiàn)有的數(shù)據(jù)。這個(gè)功能執(zhí)行的一個(gè)重要任務(wù)是處理UFO。套接字緩沖區(qū)在套接字的發(fā)送隊(duì)列中進(jìn)行管理。在塞住套接字的情況下,隊(duì)列中可以添加附加數(shù)據(jù)的條目。數(shù)據(jù)位于發(fā)送隊(duì)列中,直到udp_sendmsg確定是時(shí)候調(diào)用udp_push_pending_frames,udp_push_pending_frames完成套接字緩沖并調(diào)用udp_send_skb。 Linux內(nèi)核將數(shù)據(jù)包存儲(chǔ)在結(jié)構(gòu)sk_buff(套接字緩沖區(qū))中,所有網(wǎng)絡(luò)層都使用它來存儲(chǔ)它們的標(biāo)題,有關(guān)用戶數(shù)據(jù)(有效負(fù)載)的信息以及其他內(nèi)部信息。 內(nèi)核中的套接字緩沖區(qū)。 在上圖中,sk_buff的頭部,數(shù)據(jù),尾部和尾部成員指向存儲(chǔ)協(xié)議頭部和用戶有效載荷的內(nèi)存區(qū)域的邊界。頭部和終點(diǎn)指向分配給緩沖區(qū)的空間的開始和結(jié)束。數(shù)據(jù)和尾部指向整個(gè)空間內(nèi)的用戶數(shù)據(jù)的開始和結(jié)束。緊接在結(jié)束邊界后面,結(jié)構(gòu)skb_shared_info包含IP分片的重要信息。
內(nèi)存腐敗
如前面的POC中所示,當(dāng)?shù)谝淮握{(diào)用“send”時(shí),MSG_MORE標(biāo)志被調(diào)用,__ip_append_data通過調(diào)用ip_ufo_append_data創(chuàng)建一個(gè)新的套接字緩沖區(qū),如下面的代碼所示: 當(dāng)這個(gè)調(diào)用完成,并且創(chuàng)建了新的套接字緩沖區(qū)時(shí),用戶數(shù)據(jù)被復(fù)制到片段中,共享信息結(jié)構(gòu)被更新為片段信息,如下圖所示。新創(chuàng)建的sk_buff被放入隊(duì)列中。 在下一步中,PoC通過設(shè)置選項(xiàng)SO_NO_CHECK來更新套接字以不計(jì)算UDP上的校驗(yàn)和; 這將覆蓋套接字結(jié)構(gòu)的sk-> sk_no_check_tx成員。在__ip_append_data里面,這個(gè)變量被檢查為調(diào)用ip_ufo_append_data之前的一個(gè)條件。 在POC第二次調(diào)用“發(fā)送”的過程中,在__ip_append_data內(nèi)部采用非UFO路徑,該路徑進(jìn)入片段長度計(jì)算循環(huán)。在循環(huán)的第一次迭代期間,副本的值變?yōu)樨?fù)值,這會(huì)觸發(fā)新的套接字緩沖區(qū)分配。另外碎片計(jì)算超過MTU并觸發(fā)碎片。這會(huì)導(dǎo)致通過使用skb_copy_and_csum_bits函數(shù)將用戶有效載荷從第一個(gè)發(fā)送調(diào)用創(chuàng)建的sk_buff復(fù)制到新分配的sk_buff。這將從源緩沖區(qū)中復(fù)制指定數(shù)量的字節(jié)到目標(biāo)sk_buff并計(jì)算校驗(yàn)和。調(diào)用長度大于新創(chuàng)建的sk_buff邊界結(jié)束限制的skb_copy_and_csum_bits會(huì)覆蓋套接字緩沖區(qū)之外的數(shù)據(jù),并破壞之前為sk_buff的skb_shared_info結(jié)構(gòu)。 接下來是損壞的skb_shared_info結(jié)構(gòu)。地址0xffff88003a4ca900處的內(nèi)存是新創(chuàng)建的sk_buff,結(jié)尾= 1728,其中分段被觸發(fā)。 當(dāng)大多數(shù)默認(rèn)的Ubuntu桌面系統(tǒng)允許非特權(quán)用戶命名空間時(shí),這個(gè)bug可以被非特權(quán)用戶利用。用戶應(yīng)該可以做兩件事情: 1:建立一個(gè)啟用了UFO的接口(可能來自用戶名字空間),或者使用那個(gè)接口(如果它已經(jīng)存在)。(“l(fā)o”界面默認(rèn)啟用UFO。) 2:禁用NETIF_F_UFO接口功能或設(shè)置SO_NO_CHECK套接字選項(xiàng)。 代碼執(zhí)行可以通過在一個(gè)大緩沖區(qū)末尾簡單地創(chuàng)建一個(gè)偽造的skb_shared_info結(jié)構(gòu)并將回調(diào)成員設(shè)置為shellcode來轉(zhuǎn)移到用戶模式的shellcode。第二個(gè)“send”會(huì)觸發(fā)套接字緩沖區(qū)的超出邊界條件,用用戶模式shellcode地址覆蓋skb_shared_info-> destructor_arg,在從內(nèi)核內(nèi)存釋放sk_buff之前調(diào)用該地址。 當(dāng)暴露給非特權(quán)用戶時(shí),Linux內(nèi)核提供了一個(gè)大的攻擊面。所有的用戶應(yīng)該保持他們的系統(tǒng)補(bǔ)丁與最新的更新。本文地址:http://www.gle-technology.com/safety/25702.html