3 src 获取_CVE-2019-15846:Exim远程获取root权限漏洞分析
報(bào)告編號(hào):B6-2019-103101
報(bào)告來源:360-CERT
報(bào)告作者:360-CERT
更新日期:2019-10-31
0x00 漏洞背景
2019年9月6日18:00,exim發(fā)布exim-4.92.2版本修復(fù)了CVE-2019-15846,攻擊者可以利用此漏洞遠(yuǎn)程獲取root權(quán)限。漏洞由qualys發(fā)現(xiàn)并報(bào)告。
當(dāng)exim支持TLS時(shí),攻擊者發(fā)送以'0'結(jié)束的SNI,此時(shí)string_unprinting函數(shù)調(diào)用string_interpret_escape函數(shù)處理轉(zhuǎn)義序列,由于string_interpret_escape函數(shù)中沒有處理'0'的情況,造成了越界讀。qualys已經(jīng)證實(shí)可以利用此漏洞遠(yuǎn)程獲取root權(quán)限。
2019年10月8日,synacktiv發(fā)布POC以及漏洞分析,360CERT對(duì)此進(jìn)行復(fù)現(xiàn)和分析。
影響版本
exim < 4.92.2版本
環(huán)境搭建
(1)poc 地址:https://github.com/synacktiv/Exim-CVE-2019-15846
將1i7Jgy-0002dD-Pb-D 和1i7Jgy-0002dD-Pb-H 放入/var/spool/exim/input文件夾下,需要root權(quán)限。
(2)啟動(dòng)exim:
sudo /usr/exim/bin/exim -bd -q30m -dd
exim會(huì)在啟動(dòng)過程中去讀取配置文件,執(zhí)行到string_unprinting()漏洞函數(shù),所以不能在啟動(dòng)后用gdb附加,而且啟動(dòng)后的觸發(fā)漏洞的進(jìn)程也會(huì)退出。根據(jù)poc作者的操作是set follow-fork-mode child就可以附加到漏洞進(jìn)程,筆者按該方法無法正常啟動(dòng)exim進(jìn)行調(diào)試,所以換了個(gè)調(diào)試方法,在源碼觸發(fā)漏洞前加個(gè)等待讀取的操作,再用gdb去附加漏洞進(jìn)程。
/src/src/spool_in.c:
(3)附加漏洞進(jìn)程:
(4)進(jìn)行調(diào)試
0x01 漏洞分析
查找可利用的漏洞觸發(fā)路徑:
(1)大部分調(diào)用string_interpret_escape()的函數(shù)都對(duì)傳入的字符串有限制。例如nextitem()(src/filter.c)檢查了字符串緩沖區(qū)是否溢出。string_dequote()函數(shù)只從配置文件中獲取字符串。
(2)tls_import_cert()->string_unprinting()->string_interpret_escape()
由于證書是pem格式,用Base64編碼,所以不可能包含'0'序列
(3)src/spool_in.c
peerdn(src/spool_in.c)的使用并非默認(rèn)配置,在Exim使用客戶端證書驗(yàn)證時(shí)才會(huì)被調(diào)用
(4)最后關(guān)注到tls連接上,只要Exim支持tls連接,攻擊者就可以發(fā)送sni,據(jù)此調(diào)用到string_unprinting() 和 string_interpret_escape() 函數(shù)
tls_in.sni = string_unprinting(string_copy(big_buffer + 9));string_unprinting函數(shù)的作用是將輸入緩沖區(qū)的內(nèi)容(解析轉(zhuǎn)義字符,如通過string_interpret_escape函數(shù)x62轉(zhuǎn)成b)寫入到輸出緩沖區(qū)。
在string_unprinting中判斷''進(jìn)入string_interpret_escape流程,string_interpret_escape函數(shù)中沒有對(duì)'0'的判斷,可以繼續(xù)讀取字符串,并寫入到輸出緩存區(qū)中,因此造成越界讀的同時(shí)也越界寫了。過程如下圖所示:
剛進(jìn)入string_unprinting時(shí):s = 0x1e16de8q = ss = 0x1e16df0p = 0x1e16deeoff = 0x6len = 0x8第一次memcpy:gdb-peda$ x/10gx 0x1e16de80x1e16de8: 0x005c666564636261 0x00006665646362610x1e16df8: 0x0000000000000000 0x00000000000000000x1e16e08: 0x0000000000000000 0x00000000000000000x1e16e18: 0x0000000000000000 0x00000000000000000x1e16e28: 0x0000000000000000 0x0000000000000000進(jìn)入string_interpret_escape前p的值:gdb-peda$ p p$24 = (const uschar *) 0x1e16dee ""進(jìn)入string_interpret_escape后p的值:gdb-peda$ p p$24 = (const uschar *) 0x1e16def ""退出string_interpret_escape后p指針又自加了一次,所以一共自加兩次,導(dǎo)致向前解析了'','0'兩個(gè)字符,而'0'的下一個(gè)字符為剛剛memcpy的"abcdef",不為'0',所以while循環(huán)繼續(xù)解析,導(dǎo)致第二次memcpy:
Guessed arguments:arg[0]: 0x1e16df7 --> 0x0 arg[1]: 0x1e16df0 --> 0x666564636261 ('abcdef')arg[2]: 0x6 arg[3]: 0x7 第二次memcpy后:gdb-peda$ x/10gx 0x1e16de80x1e16de8: 0x005c666564636261 0x61006665646362610x1e16df8: 0x0000006665646362 0x00000000000000000x1e16e08: 0x0000000000000000 0x00000000000000000x1e16e18: 0x0000000000000000 0x00000000000000000x1e16e28: 0x0000000000000000 0x0000000000000000從越界讀導(dǎo)致越界寫。
exgen.py 構(gòu)造的文件通過對(duì)堆的布局(需要在/var/spool/exim/input文件夾下放至少205個(gè)message-log文件),通過堆溢出將保存在堆中的文件名修改成../../../../../tmp/tote,并偽造sender_address,之后該字段保存的字符串會(huì)寫入message-log文件(即../../../../../tmp/tote)中。
但該poc在測(cè)試環(huán)境中,堆無法布局成功(可能環(huán)境以及205個(gè)message-log文件不同),會(huì)覆蓋top chunk,造成進(jìn)程崩潰,但主進(jìn)程會(huì)重新起進(jìn)程。
使用exgen.py造成的堆布局(進(jìn)入string_unprinting函數(shù)后)如下:
0x1210c10 0x2e000083 0x4010 Used None None0x1214c20 0x0 0x2020 Used None None0x1216c40 0x0 0x2ff0 Used None None0x1219c30 0x0 0x2020 Used None None0x121bc50 0x0 0x410 Used None Nonegdb-peda$ p s$6 = (uschar *) 0x1219ca0 'a' , "x00x00x00x00x00x00x00x00x00x20x00x00x00x00x00x00aaaaaaaaax2ex2ex2fx2e"...gdb-peda$ p len$14 = 0xfc8gdb-peda$ p yield_length $17 = {0x20, 0x1ae8, 0xffffffff}之后堆溢出破壞了top chunk:
0x1210c10 0x2e000083 0x4010 Used None None0x1214c20 0x0 0x2020 Used None None0x1216c40 0x0 0x2ff0 Used None None0x1219c30 0x0 0x2020 Used None NoneCorrupt ?!導(dǎo)致后面分配時(shí)錯(cuò)誤,產(chǎn)生崩潰:
0x02 補(bǔ)丁分析
在string_interpret_escape函數(shù)中判斷''后面是否為'0',如果是就不再自加一次,直接返回''所在的地址。退出string_interpret_escape后在string_unprinting自加一次p指針指向'0'的地址,while循環(huán)結(jié)束,不會(huì)造成越界讀。
0x03 時(shí)間線
2019-09-06 exim發(fā)布新版本修復(fù)漏洞
2019-09-06 360CERT發(fā)布預(yù)警
2019-10-08 synacktiv發(fā)布poc
2019-10-31 360CERT對(duì)外發(fā)布漏洞分析報(bào)告
0x04 參考鏈接
歡迎加入360-CERT團(tuán)隊(duì),請(qǐng)投遞簡(jiǎn)歷到 caiyuguang[a_t]360.cn
總結(jié)
以上是生活随笔為你收集整理的3 src 获取_CVE-2019-15846:Exim远程获取root权限漏洞分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么开通qq在线客服(怎么开通qq在线客
- 下一篇: ps怎么做纸张撕裂的效果(ps怎么做纸张