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