10

D-Link DIR878路由器命令执行漏洞分析

 3 years ago
source link: https://www.freebuf.com/vuls/237533.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

本文复现了D-Link DIR878型号当中存在的一个命令执行漏洞,漏洞编号CVE-2019-8316, 漏洞链接

本文分为以下几个部分:

 1.环境搭建
 2.固件解密解压
 3.漏洞分析
 4.动态测试

一、环境搭建

本文章的实验环境:win10主机,firefox浏览器设置代理,BurpSuiteCommunity实现抓包以及修改报文,逆向分析工具ghidra;Linux虚拟机,版本1804,安装binwalk以及7z。

我手头上有DIR878型号的路由器,所以我直接通过无线网络连接到路由器上,内网地址:192.168.0.1。如果没有路由器的朋友可以参考qemu搭建模拟环境的这个链接,不过非常的繁琐我自己也没有搭建完成。

fe6BNrB.jpg!web

虚拟机上首先安装qemu组件,执行命令:sudo apt install qemu-utils(注:我不是要用qemu来模拟路由器,只是后面的解密固件需要用到qemu)。安装完成后查看组件,执行命令:ls /usr/bin,查看是否有qemu-mipsel-static组件,有则说明可以正常使用了。

EriQJbf.jpg!web

二、固件解密解压

固件的解密参考了 解密链接 ,我结合链接当中的过程,描述一下自己的解密过程以及遇到的问题。

DIR878型号的路由器采用链接当中提到的第一种形式,最初几个版本不加密,从中间某个版本之后开始加密,而解密文件存放在开始加密的前一个版本,也就是最后一个不加密的版本,878型号当中的这个固件版本是1.04,可以在 官网 根据路由器型号查找到各个版本的固件。如图所示,我们采用的固件版本是最新的1.20,包含解密文件的版本是1.04,放在和第一个加密版本1.10一起。

FFzQJbE.jpg!web

2eu2quN.jpg!web

我们首先尝试解压1.20的固件,可以发现没有任何的输出,可以判定固件已经被加密了。

YBze6zu.jpg!web

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

a632ey.jpg!web

接下来进入提取出来的路径,提取文件系统:binwalk -e A0,在cpio-root路径下就可以看到整个文件系统,熟悉Linux的朋友可能很快就发现和Linux的目录结构是一样的。

nmMjQba.jpg!web

进入bin目录,可以发现存在一个imgdecrypt,可以用来解密固件的文件。 

qYRjQj6.jpg!web

返回主目录cpio-root,在第一步当中提到的qemu-mispel-static,把这个文件复制到./usr/bin目录下,执行命令:cp /usr/bin/qemu-mispel-static ./usr/bin,此处踩坑:

JRBvYny.jpg!web 查阅资料其实是因为存储空间不够,按道理来说我的虚拟机存储空间是非常大的,绝对不可能出现这种情况,所以怀疑是解压过程当中解压完压缩文件,原文件仍旧保留,所以我把上级目录下的其他文件都删除了,只保留了cpio-root这个文件系统,再尝试就成功了

eI3uUjy.jpg!web 然后复制需要解密的固件到主目录,命令:cp /home/test/Desktop/firmare/1_20/DIR_878_FW120B05.BIN .

jA7VRfr.jpg!web

接下来利用qemu,启动mips虚拟执行环境,进入busybox,命令:chroot . /bin/sh

BBRze2J.jpg!web 然后利用解密文件解密,可以看到解密成功,输出了key。

yQvU3me.jpg!web 利用binwalk开始对解密完的固件解压,(注:此处有坑)

6NbAV3V.jpg!web 报错显示解压失败,我们进到目录里面也只能看到7z文件,根本看不到解压出来的文件系统,原因是系统没有安装7z工具,平时解压的时候压缩软件都带着解压7z的功能,所以我们误认为系统中带有7z的解压命令,其实不然,可以在命令行输入7z尝试一下就会发现并没有这个工具,跟据他的输入提示,安装7z工具,然后就可以在命令行用7z命令了。

iIvYJvE.jpg!web 可以看到现在解压成功了,后续提取文件系统也是和之前一样的操作。

三、漏洞分析

根据漏洞编号CVE-2019-8316当中的介绍,命令注入存在于站点过滤功能,把分析定位到这个方向。

首先利用ghidra进行反编译,这里提一下,IDA的可视化功能非常强大,可以看到程序流图,但是只支持ARM架构,如果要分析本路由器的话需要安装别的插件,ghidra的反编译功能则比较强大,可以反编译成C程序,可读性更高,我采用的是ghidra。ghidra新建项目后,把librcm.so文件拉入工程中进行反编译,首先定位到站点过滤函数:

RrYvEjz.jpg!web 可以看到大部分的处理时文件读写,涉及到的也只是常量,唯一值得怀疑的时FUN_0002fef0函数,后面8位代表地址,进入这个函数分析:

F3AjEzE.jpg!web

这个函数比较大,有两百多行,(这里剧透一下这个函数有问题),然后查看一下这个函数被哪些函数调用以及调用了哪些函数

mauYriB.jpg!web 可以发现出了刚刚的add_url_filter_iptables_rule函数还有别的函数调用,所以后面测试的时候发现有两个地方可以注入命令,都是利用这同一个漏洞。

iE7vQfm.jpg!web 查看本函数的调用函数,发现twsystem这种系统调用函数,显然只要注入的命令能被这个系统函数调用就可以实现命令注入,所以我们来详细分析这个函数在内部时怎么调用系统函数的:

ENzmqu6.jpg!webzqQf2iR.jpg!web 这里我用vscode作为编辑器,平时用的多比较习惯,我只截取关键部分,前面的功能我概括一下,就是对用户输入的url进行预处理,提取出域名,然后执行系统函数来实现站点过滤,我们仔细分析这一部分,被系统函数执行的参数一个是常数1,另一个是变量acStack544,只有这个变量是可能被注入的,回溯一下164行对acStack544进行初始化置零,后面进行了很多操作,大部分都是常量字符串来拼接,出现的变量仅有183行的local_268和188行的local_264,这两个变量就是我前面说的预处理得到的域名,url的处理主要根据/ ? 等特殊字符来进行切割的,感兴趣的朋友可以自己读函数。

经过我们的分析,可以发现这里对url的处理并不能过滤命令注入,所以twsystem函数会执行用户注入的命令,接下来开始动态测试来验证我们的分析。

四、动态测试

首先来到站点过滤的地方,尝试在前端直接注入命令,发现不行这里有对特殊字符的限制,没办法直接注入命令。

jiqyum7.jpg!web

所以只能采用burpsuite抓包改报文的方式来实现命令注入,首先随意输入一个合法的url,此处已 www.baidu.com 为例,保存设置,截下前端发送的报文:

ZJziuaM.jpg!webamaueum.jpg!web

对报文当中的url字段进行修改,注入命令:$(telnetd -l sh -p 1337 -b 0.0.0.0),开放路由器的1337端口等待他人连接

JzEzQbu.jpg!web 注意:此处踩坑,之前采用的命令是telnetd -l /bin/sh -p 1337 -b 0.0.0.0,我们提到了url的预处理过程,函数会根据/来截取域名,例如 https://github.com/projectxxx ,协议后面有两个/,域名结束后也存在/,如果我们注入的命令存在/,就会被处理掉,所以后面注入命令采用我上面写的那条命令。

改完报文发送过去之后,就可以看到我们的设置成功了,也就是注入的命令被执行了

yaE7raZ.jpg!web

我们前面静态分析的时候提到了,还有其他函数调用了漏洞函数,在 禁止客户端存取下列清单中的网站选项那里,还可以选择另外一个选项,然后和我们上面一样的步骤,也能够顺利注入命令,因为这两个函数都调用了分析的漏洞函数。

接下来在主机尝试telnet连接路由器,验证一下我们注入的命令被成功执行:

Uz2EnmI.jpg!web

BNNZr22.jpg!web 可以看到此时已经成功控制了路由器的shell。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK