作者:0431實驗室
公眾號:吉林省信睿網絡
0x01.漏洞概述
1.簡介
CVE-2019-1663是一個影響Cisco的多個低端設備的堆棧緩沖區,由于管理界面沒有對登錄表單的pwd字段進行嚴格的過濾,底層在處理請求時,strcpy函數導致堆棧溢出,未經身份驗證的遠程攻擊者可以在設備上執行任意代碼
2.影響的版本:
Cisco RV110W <1.2.1.7
Cisco RV130/RV130W <1.0.3.45
Cisco RV215W <1.3.0.8
0x02.固件提取
這里我使用時Cisco RV130W 1.0.3.44進行測試的,binwalk對固件進行提取

可以看出文件系統是squashfs,并且是小端存儲方式,得到一個類Linux目錄

0x03.分析處理請求
使用 grep -r "http"來查找處理http請求的二進制文件

根據之前分析的多個嵌入式設備的經驗,猜測這個可能就是處理http請求的底層文件
0x04.漏洞分析
對Web登錄界面的login.cgi發送如下的POST請求
POST /login.cgi HTTP/1.1
Host: 10.10.10.2
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://10.10.10.2/
Content-Type: application/x-www-form-urlencoded
Content-Length: 137
Connection: close
Upgrade-Insecure-Requests: 1
submit_button=login&submit_type=&gui_action=&wait_time=0&change_action=&enc=1&user=cisco&pwd=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&sel_lang=EN
這里向pwd發送32字節的值,對登錄界面的http處理請求在IDA中的是sub_2C614(),地址是0x0002C614

函數將POST請求的參數進行解析,存儲到.bss段

然后,將pwd參數的值從.bss段中提取,調用strcpy將值存到動態分配的內存中

對于strcpy我們都很熟悉,它存在的安全問題也十分嚴峻,并且由于沒有開啟PIE / ASLR,所以可以隨意的進行溢出操作
這里使用gdb進行遠程調試,確定能夠發生溢出的字節數,首先設置cisco,作為gdb調試的服務端,gdbserver配置
# wget http://10.10.10.1:8000/gdbserver //從本機下載到qemu模擬的cisco環境中
#chmod 777 ./gdbserver //給權限
# ps -w | grep httpd //查找httpd開啟的進程號
2451 0 5472 S ./usr/sbin/httpd
2454 0 1196 S grep httpd
# ./gdbserver :1234 --attach 2451 //這里的1234是開啟監聽的端口號,--attach添加的是httpd的進程號
Attached; pid = 2451
Listening on port 1234
//然后成功監聽
編譯arm-gdb-linux
tar xvf gdb-7.8.1.tar.gz
cd gdb-7.8.1
mkdir arm-gdb
sudo chmod 777 arm-gdb
sudo apt-get install texinfo
./configure --target=arm-linux --prefix=/home/clb/1tools/gdb-7.8.1/arm-gdb
make && make install
然后在arm-gdb下的bin目錄中就有用于調試的arm-linux-gdb,配置調試選項
./arm-linux-gdb
gef> set architecture arm //確定要調試的是arm架構
gef> set follow-fork-mode child //確定調試的進程
gef> set solib-search-path /home/clb/1iot/firmware/cisco/_RV130.bin.extracted/squashfs-root/lib/ //加載要用到的lib文件
gef> file /home/clb/1iot/firmware/cisco/_RV130.bin.extracted/squashfs-root/usr/sbin/httpd //加載調試文件
gef> target remote 10.10.10.2:1234 //與遠程建立連接
已經建立調試連接,可以進行調試了
查找溢出的位置,使用pattern生成512個字符串
gef? patter create 512
[+] Generating a pattern of 512 bytes
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaaf
[+] Saved as '$_gef0'
通過curl發送POST請求查找溢出的位置
gef? c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x616d6560 in ?? ()
通過pattern確定溢出的大小
gef? pattern search 0x616d6561
[+] Searching '0x616d6561'
[+] Found at offset 446 (little-endian search) likely
我們可以確定要進行填充的字符串是有446個字節
這里使用Ret2Libc進行利用。ret2libc 這種攻擊方式主要是針對 動態鏈接(Dynamic linking) 編譯的程序,因為正常情況下是無法在程序中找到像 system() 、execve() 這種系統級函數(如果程序中直接包含了這種函數就可以直接控制返回地址指向他們,而不用通過這種麻煩的方式)。因為程序是動態鏈接生成的,所以在程序運行時會調用 libc.so (程序被裝載時,動態鏈接器會將程序所有所需的動態鏈接庫加載至進程空間,libc.so 就是其中最基本的一個),libc.so 是 linux 下 C 語言庫中的運行庫glibc 的動態鏈接版,并且 libc.so 中包含了大量的可以利用的函數,包括 system() 、execve() 等系統級函數,我們可以通過找到這些函數在內存中的地址覆蓋掉返回地址來獲得當前進程的控制權。通常情況下,我們會選擇執行 system(“/bin/sh”) 來打開 shell。這里我們使用vmmap查看調用的lib文件有哪些

注:由于是在模擬器中查找的lib文件的起始地址,所以和在真機中的地址可能不太一樣
這里我們選擇具有執行權限的libc.so.0文件,使用radare2對libc.so.0文件進行搜索system函數

這里的system函數的地址是偏移地址,偏移地址加上vmmap得到的起始地址就是,我們通過下斷點得到system函數的地址,然后通過計算可以發現地址完全正確

這時我們已經知道了一些關鍵的地址,那么這個時候我們就需要構造一個 ROP鏈,來實現地址的跳轉
這里使用了一款工具Ropper,因為我們存儲的位置位于堆棧,所以查找跟堆棧有關的指針SP

這里我選擇了0x00041308的指令,因為這里有一個關于指令跳轉的指令BLX,如果r2存的值是system的地址,那么我們就能跳到system處,執行系統命令了,并且由于我們的值都存在棧中,所以我們就需要查找和pop,r2有關的指令

在ARM指令集下我們發現兩個對r2的操作,但是后面還跟著別的指令,如果我們使用了某一個,那么我們還得繼續尋找能夠完整構造payload的指令。由于ARM除了有ARM指令外,還有一個Thumb指令集,這個指令是ARM指令集的一個子集,但是在某些方面比ARM指令集要更有效,我們切換指令集去這里看看符合我們要求的指令

這里我們找到了沒有其他指令參與并且堆棧操作十分符合我們要求的指令,下面就是我們構造的堆棧的排列方式

首先排布的是target1,這條指令就是對棧就行彈出的操作,首先將system的地址彈出到r2,然后后面無用的地址彈出到r6,最后將target2的地址彈出到r15中,并且r15中存儲的還是正在取指的地址。緊接著執行r15所指向的地址,首先將sp的地址存儲到r0中,然后執行blx跳轉指令并且切換指令集,并且跳轉到r2的地址,也就是system的地址,那么這時候就成功執行system函數,到此整個ROP鏈也就執行完畢
0x05.漏洞利用
這里我們利用的是exploit-db上的exp

設置rhosts,lhosts和target,然后直接exploit,就能直接獲得shell權限,這里我在vps上執行的

成功執行ifconfig命令
0x06.EXP腳本分析

這里存儲就是偏移地址,libc_base的地址,system的偏移地址,gadget1的偏移地址,gadget2的偏移地址,這些地址就是真機中真正的偏移地址

這里就是根據不同的target生成不同的payload

這里就是我們對Msf生成的payload進行輸出,可以看到被攻擊的設備下載了可以在ARM平臺進行回來的文件,并給與權限并執行,最終創建一個shell
0x07.參考
1.https://github.com/hugsy/gdb-static/
3.https://github.com/sashs/Ropper
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.jmbmsq.com/1039/
暫無評論