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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

Linux提权CVE-2022-0847分析

發(fā)布時(shí)間:2025/3/21 linux 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux提权CVE-2022-0847分析 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

漏洞利用原理:

通過(guò)pipe生成一個(gè)管道,然后使用write調(diào)用pip_write將管道填滿flag為PIPE_BUF_FLAG_CAN_MERGE,然后用read將緩沖區(qū)全部釋放,但是根據(jù)splice進(jìn)行零拷貝時(shí)copy_page_to_iter_pipe沒(méi)有將flag初始化,導(dǎo)致緩沖區(qū)仍然留存PIPE_BUF_FLAG_CAN_MERGE。進(jìn)而在write上檢測(cè)flag存在PIPE_BUF_FLAG_CAN_MERGE來(lái)達(dá)成越權(quán)寫(xiě)入操作。

什么是零拷貝?

零拷貝是作用于兩個(gè)文件間移動(dòng),正常文件拷貝流程一般為cpu對(duì)內(nèi)存空間進(jìn)行多次讀寫(xiě)操作將拷貝數(shù)據(jù)從用戶態(tài)到內(nèi)核態(tài)再返回用戶態(tài),而零拷貝讓數(shù)據(jù)不需要經(jīng)過(guò)用戶態(tài),而是將內(nèi)核緩沖區(qū)與用戶程序進(jìn)行共享,這樣就不需要把內(nèi)核緩沖區(qū)的內(nèi)容往用戶空間拷貝。應(yīng)用程序再調(diào)用write(),操作系統(tǒng)直接將內(nèi)核緩沖區(qū)的內(nèi)容傳輸?shù)街付ㄝ敵龆肆恕?br /> 具體的文件通過(guò)管道傳輸流程:
in端 == write == pipe == splice == out端
out端通過(guò)splice與內(nèi)核緩沖區(qū)進(jìn)行共享,然后in端調(diào)用write將內(nèi)容拷貝到內(nèi)核緩沖區(qū)進(jìn)而寫(xiě)入到out端。

【→所有資源關(guān)注我,私信回復(fù)“資料”獲取←】
1、網(wǎng)絡(luò)安全學(xué)習(xí)路線
2、電子書(shū)籍(白帽子)
3、安全大廠內(nèi)部視頻
4、100份src文檔
5、常見(jiàn)安全面試題
6、ctf大賽經(jīng)典題目解析
7、全套工具包
8、應(yīng)急響應(yīng)筆記

設(shè)置緩沖區(qū)flag為PIPE_BUF_FLAG_CAN_MERGE

分析pipe_write函數(shù)源碼


當(dāng)我們給pipe->tmp_pipe = NULL下斷點(diǎn)后,可以看到當(dāng)我們執(zhí)行exp后的flags設(shè)置為0x10(PIPE_BUF_FLAG_CAN_MERGE)


這里的page = 0xffffea00001b09c0,是我們write申請(qǐng)的頁(yè),然后用于與內(nèi)核緩沖區(qū)進(jìn)行數(shù)據(jù)傳輸
根據(jù)堆棧回溯可以看到,這個(gè)只是調(diào)用write時(shí)會(huì)將flags設(shè)置為PIPE_BUF_FLAG_CAN_MERGE

static void prepare_pipe(int p[2]) {if (pipe(p)) abort(); //這里要查看一下pipe的棧回溯調(diào)用鏈const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ); //調(diào)用pipe.c *1392static char buffer[4096];/* fill the pipe completely; each pipe_buffer will now havethe PIPE_BUF_FLAG_CAN_MERGE flag */for (unsigned r = pipe_size; r > 0;) {unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;write(p[1], buffer, n);r -= n;}/* drain the pipe, freeing all pipe_buffer instances (butleaving the flags initialized) */for (unsigned r = pipe_size; r > 0;) {unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;read(p[0], buffer, n);r -= n;}/* the pipe is now empty, and if somebody adds a newpipe_buffer without initializing its "flags", the bufferwill be mergeable */ }

上述代碼實(shí)質(zhì)就是將pipe緩沖區(qū)所以flag設(shè)置為PIPE_BUF_FLAG_CAN_MERGE,然后調(diào)用read是釋放pipe緩沖區(qū)來(lái)讓緩沖區(qū)變?yōu)殚e置等待調(diào)用狀態(tài),進(jìn)而讓flag為PIPE_BUF_FLAG_CAN_MERGE執(zhí)行下一次exp中的write。
但是我們只關(guān)注flag上的PIPE_BUF_FLAG_CAN_MERGE,那么調(diào)用read后會(huì)不會(huì)將flags上的PIPE_BUF_FLAG_CAN_MERGE呢?

splice實(shí)現(xiàn)零拷貝傳輸

在調(diào)用splice時(shí)會(huì)調(diào)用到__copy_page_to_iter
下面是splice的調(diào)用鏈:(查看copy_page_to_iter_pipe堆棧平衡得出)

sys_splice __do_splice ==> do_splice ===> splice_file_to_pipe ====> generic_file_splice_read =====> call_read_iter ======> copy_folio_to_iter =======> flimap_read ========> copy_folio_to_iter =========> copy_page_to_iter ==========> __copy_page_to_iter ===========> copy_page_to_iter_pipe

在splice_file_to_pipe上存在3種調(diào)用情況:

  • in/out都是pipe類型
  • in是pipe類型
  • out是pipe類型(這是exp調(diào)用類型)

如下即為exp使用的第三種splice零拷貝的源碼:


上面只校驗(yàn)了out端是否為pipe類型,然后檢測(cè)執(zhí)行程序用戶是否對(duì)root權(quán)限文件具有讀寫(xiě)操作,然后就調(diào)用splice_file_to_pipe來(lái)進(jìn)行下一步漏洞利用。

注意下面這個(gè)判斷:

if (off_in) { //這里限制了只能從偏移值1開(kāi)始if (!(in->f_mode & FMODE_PREAD)) //判斷輸入是否有讀權(quán)限,所以exp只需要對(duì)輸出到的root權(quán)限文件具有可讀權(quán)限r(nóng)eturn -EINVAL;offset = *off_in;} else { .....

if (off_in) {判斷是導(dǎo)致進(jìn)行越權(quán)寫(xiě)入偏移值必須為0的原因。

分析copy_page_to_iter_pipe


上述即為splice零拷貝過(guò)程中“out端與內(nèi)核緩沖區(qū)共享”的調(diào)用源碼
可以看到,由于是頁(yè)引用行為,所以我們傳輸?shù)臄?shù)據(jù)大小不能大于原文件大小。
補(bǔ)丁上也是在這個(gè)文件上對(duì)緩沖區(qū)的flag進(jìn)行了初始化操作。
那么我們可以得知,只要在這里對(duì)flag進(jìn)行初始化,就不可能導(dǎo)致越權(quán)讀寫(xiě)產(chǎn)生,那么說(shuō)明了判定flag存在PIPE_BUF_FLAG_CAN_MERGE進(jìn)而達(dá)到下一步利用這個(gè)過(guò)程是不在splice上的。
下面是利用代碼:

ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0); //將指定文件的內(nèi)容從指定offset開(kāi)始copy到p[1]上,長(zhǎng)度為1字節(jié)

調(diào)用write連接pipe進(jìn)行splice零拷貝時(shí)的檢測(cè)手段

分析零拷貝中所有涉及函數(shù)可知,只有在調(diào)用pipe_write時(shí)存在檢測(cè)操作。
分析pipe_write:
當(dāng)緩沖區(qū)上的flag為PIPE_BUF_FLAG_CAN_MERGE則直接調(diào)用copy_page_from_iter對(duì)數(shù)據(jù)進(jìn)行管道寫(xiě)入操作,進(jìn)而達(dá)成越權(quán)寫(xiě)。


所以可以知道read釋放緩沖區(qū)時(shí)沒(méi)有對(duì)flag進(jìn)行初始化操作。
下面是利用代碼:

nbytes = write(p[1], data, data_size); //這里開(kāi)始觸發(fā)任意文件寫(xiě)入,將我們指定的內(nèi)容copy到p[1]上

關(guān)于參數(shù)測(cè)試


經(jīng)案例上使用的"root"可以使用,而""root"可以使用,而""root"使"root"無(wú)輸出

總結(jié)

以上是生活随笔為你收集整理的Linux提权CVE-2022-0847分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。