本文復現了D-Link DIR878型號當中存在的一個命令執行漏洞,漏洞編號CVE-2019-8316,漏洞鏈接。

本文分爲以下幾個部分:

1.環境搭建

2.固件解密解壓

3.漏洞分析

4.動態測試

本文章的實驗環境:win10主機,firefox瀏覽器設置代理,BurpSuiteCommunity實現抓包以及修改報文,逆向分析工具ghidra;Linux虛擬機,版本1804,安裝binwalk以及7z。

我手頭上有DIR878型號的路由器,所以我直接通過無線網絡連接到路由器上,內網地址:192.168.0.1。如果沒有路由器的朋友可以參考qemu搭建模擬環境的這個鏈接,不過非常的繁瑣我自己也沒有搭建完成。

虛擬機上首先安裝qemu組件,執行命令:sudo apt install qemu-utils(注:我不是要用qemu來模擬路由器,只是後面的解密固件需要用到qemu)。安裝完成後查看組件,執行命令:ls /usr/bin,查看是否有qemu-mipsel-static組件,有則說明可以正常使用了。

二、固件解密解壓

固件的解密參考了,我結合鏈接當中的過程,描述一下自己的解密過程以及遇到的問題。

DIR878型號的路由器採用鏈接當中提到的第一種形式,最初幾個版本不加密,從中間某個版本之後開始加密,而解密文件存放在開始加密的前一個版本,也就是最後一個不加密的版本,878型號當中的這個固件版本是1.04,可以在根據路由器型號查找到各個版本的固件。如圖所示,我們採用的固件版本是最新的1.20,包含解密文件的版本是1.04,放在和第一個加密版本1.10一起。

我們首先嚐試解壓1.20的固件,可以發現沒有任何的輸出,可以判定固件已經被加密了。

所以首先提取包含解密文件的舊版本1.04,在固件目錄下輸入命令:binwalk -Me xxxx

接下來進入提取出來的路徑,提取文件系統:binwalk -e A0,在cpio-root路徑下就可以看到整個文件系統,熟悉Linux的朋友可能很快就發現和Linux的目錄結構是一樣的。

進入bin目錄,可以發現存在一個imgdecrypt,可以用來解密固件的文件。

返回主目錄cpio-root,在第一步當中提到的qemu-mispel-static,把這個文件複製到./usr/bin目錄下,執行命令:cp /usr/bin/qemu-mispel-static ./usr/bin,此處踩坑:

查閱資料其實是因爲存儲空間不夠,按道理來說我的虛擬機存儲空間是非常大的,絕對不可能出現這種情況,所以懷疑是解壓過程當中解壓完壓縮文件,原文件仍舊保留,所以我把上級目錄下的其他文件都刪除了,只保留了cpio-root這個文件系統,再嘗試就成功了

然後複製需要解密的固件到主目錄,命令:cp /home/test/Desktop/firmare/1_20/DIR_878_FW120B05.BIN .

接下來利用qemu,啓動mips虛擬執行環境,進入busybox,命令:chroot . /bin/sh

然後利用解密文件解密,可以看到解密成功,輸出了key。

利用binwalk開始對解密完的固件解壓,(注:此處有坑)

報錯顯示解壓失敗,我們進到目錄裏面也只能看到7z文件,根本看不到解壓出來的文件系統,原因是系統沒有安裝7z工具,平時解壓的時候壓縮軟件都帶着解壓7z的功能,所以我們誤認爲系統中帶有7z的解壓命令,其實不然,可以在命令行輸入7z嘗試一下就會發現並沒有這個工具,跟據他的輸入提示,安裝7z工具,然後就可以在命令行用7z命令了。

可以看到現在解壓成功了,後續提取文件系統也是和之前一樣的操作。

三、漏洞分析

根據漏洞編號CVE-2019-8316當中的介紹,命令注入存在於站點過濾功能,把分析定位到這個方向。

首先利用ghidra進行反編譯,這裏提一下,IDA的可視化功能非常強大,可以看到程序流圖,但是隻支持ARM架構,如果要分析本路由器的話需要安裝別的插件,ghidra的反編譯功能則比較強大,可以反編譯成C程序,可讀性更高,我採用的是ghidra。ghidra新建項目後,把librcm.so文件拉入工程中進行反編譯,首先定位到站點過濾函數:

可以看到大部分的處理時文件讀寫,涉及到的也只是常量,唯一值得懷疑的時FUN_0002fef0函數,後面8位代表地址,進入這個函數分析:

這個函數比較大,有兩百多行,(這裏劇透一下這個函數有問題),然後查看一下這個函數被哪些函數調用以及調用了哪些函數

可以發現出了剛剛的add_url_filter_iptables_rule函數還有別的函數調用,所以後面測試的時候發現有兩個地方可以注入命令,都是利用這同一個漏洞。

查看本函數的調用函數,發現twsystem這種系統調用函數,顯然只要注入的命令能被這個系統函數調用就可以實現命令注入,所以我們來詳細分析這個函數在內部時怎麼調用系統函數的:

這裏我用vscode作爲編輯器,平時用的多比較習慣,我只截取關鍵部分,前面的功能我概括一下,就是對用戶輸入的url進行預處理,提取出域名,然後執行系統函數來實現站點過濾,我們仔細分析這一部分,被系統函數執行的參數一個是常數1,另一個是變量acStack544,只有這個變量是可能被注入的,回溯一下164行對acStack544進行初始化置零,後面進行了很多操作,大部分都是常量字符串來拼接,出現的變量僅有183行的local_268和188行的local_264,這兩個變量就是我前面說的預處理得到的域名,url的處理主要根據/ ? 等特殊字符來進行切割的,感興趣的朋友可以自己讀函數。

經過我們的分析,可以發現這裏對url的處理並不能過濾命令注入,所以twsystem函數會執行用戶注入的命令,接下來開始動態測試來驗證我們的分析。

四、動態測試

首先來到站點過濾的地方,嘗試在前端直接注入命令,發現不行這裏有對特殊字符的限制,沒辦法直接注入命令。

所以只能採用burpsuite抓包改報文的方式來實現命令注入,首先隨意輸入一個合法的url,此處已www.baidu.com爲例,保存設置,截下前端發送的報文:

對報文當中的url字段進行修改,注入命令:$(telnetd -l sh -p 1337 -b 0.0.0.0),開放路由器的1337端口等待他人連接

注意:此處踩坑,之前採用的命令是telnetd -l /bin/sh -p 1337 -b 0.0.0.0,我們提到了url的預處理過程,函數會根據/來截取域名,例如https://github.com/projectxxx,協議後面有兩個/,域名結束後也存在/,如果我們注入的命令存在/,就會被處理掉,所以後面注入命令採用我上面寫的那條命令。

改完報文發送過去之後,就可以看到我們的設置成功了,也就是注入的命令被執行了

我們前面靜態分析的時候提到了,還有其他函數調用了漏洞函數,在 禁止客戶端存取下列清單中的網站選項那裏,還可以選擇另外一個選項,然後和我們上面一樣的步驟,也能夠順利注入命令,因爲這兩個函數都調用了分析的漏洞函數。

接下來在主機嘗試telnet連接路由器,驗證一下我們注入的命令被成功執行:

可以看到此時已經成功控制了路由器的shell。

*本文作者:黃培揚payoung,轉載請註明來自FreeBuf.COM

相關文章