PoC Archive PoC Archive
Critical CVE-2026-12485 patched

GeoVision GV-I/O Box 4E DVRSearch Unauthenticated Stack Buffer Overflow RCE (CVE-2026-12485)

by Cisco Talos Intelligence (discovery, TALOS-2026-2377); Ashraf Zaryouh / 0xBlackash (PoC) · 2026-06-30

CVSS 10.0/10
Severity
Critical
CVE
CVE-2026-12485
Category
network
Affected product
GeoVision GV-I/O Box 4E (Linux-based smart embedded I/O device)
Affected versions
Firmware v2.09 and earlier
Disclosed
2026-06-30
Patch status
patched

Metadata

FieldValue
Date Added2026-06-30
Last Updated2026-06-30
Author / ResearcherCisco Talos Intelligence (discovery, TALOS-2026-2377); Ashraf Zaryouh / 0xBlackash (PoC)
CVE / AdvisoryCVE-2026-12485
Categorynetwork
SeverityCritical
CVSS Score10.0 (CVSSv3.1; AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
StatusPoC
TagsRCE, unauthenticated, stack-overflow, buffer-overflow, IoT, GeoVision, DVR, embedded, UDP, network, Python, CVSS-10
RelatedN/A

Affected Target

FieldValue
Software / SystemGeoVision GV-I/O Box 4E (Linux-based smart embedded I/O device)
Versions AffectedFirmware v2.09 and earlier
Language / PlatformPython (PoC); Linux ARM/MIPS (target firmware)
Authentication RequiredNo (unauthenticated, network-accessible)
Network Access RequiredYes (UDP port 10001)

Summary

CVE-2026-12485 is a CVSS 10.0 unauthenticated stack-based buffer overflow in the GeoVision GV-I/O Box 4E, a Linux-based smart I/O device used in physical security and building automation. The DVRSearch service listens on UDP port 10001 and handles CMD_IP_SET commands for network configuration. The handler performs an unsafe memcpy() of user-controlled data into a fixed-size stack buffer without length validation, enabling remote code execution with no authentication required. Discovered by Cisco Talos Intelligence (TALOS-2026-2377). Fixed in firmware v2.12.


Vulnerability Details

Root Cause

In the DVRSearch service’s CMD_IP_SET handler, the IP address field from the incoming UDP packet is copied into a fixed-size stack buffer:

1
memcpy(&reply_buf[36], g_network_config->ip_addr, v3);

The length parameter v3 is taken directly from the attacker-controlled packet without bounds checking. Sending a payload larger than the stack buffer overwrites the return address and enables arbitrary code execution.

CWE-121 (Stack-Based Buffer Overflow).

Attack Steps

  1. Identify the target device on the network (UDP/10001 responds to probe packets).
  2. Craft a malicious UDP CMD_IP_SET packet with an oversized IP address field.
  3. Send the packet to UDP port 10001 on the target device.
  4. Stack buffer overflow overwrites the return address; payload executes as root on the device.

Impact

  • Full unauthenticated remote code execution as root on the embedded device.
  • Complete device compromise: firmware modification, persistence, pivot to adjacent networks.
  • Physical security risk: GV-I/O Box 4E controls physical I/O such as door locks, alarms, and access control relays.
  • Device not authenticated by default; typically internet- or LAN-exposed in building automation environments.

Environment / Lab Setup

Target:   GeoVision GV-I/O Box 4E, firmware v2.09 or earlier
Attacker: Python 3 with socket library
Network:  UDP/10001 reachable from attacker

Proof of Concept

Detection / Checker Script

The PoC (CVE-2026-12485.py) is a safe detection script that probes for the DVRSearch service and performs length tests without triggering the overflow:

1
2
3
git clone https://github.com/0xBlackash/CVE-2026-12485
cd CVE-2026-12485
python3 CVE-2026-12485.py <TARGET_IP>

Expected Output (Vulnerable Device)

[*] Sending probe to 192.168.1.50:10001...
[*] Received response (128 bytes) from 192.168.1.50:10001
[*] DVRSearch service detected.
[*] Length test — Size 50  -> Response received (128 bytes)
[*] Length test — Size 100 -> Response received (128 bytes)
[*] Length test — Size 200 -> Response received (128 bytes)
[!] Service appears active. Update firmware immediately (GV-IOBOX_2026-06-01).

Detection & Indicators of Compromise

1
2
3
nmap -sU -p 10001 192.168.1.0/24 --open

tcpdump -n -i eth0 udp port 10001

Mitigation (without patching):

1
iptables -A INPUT -p udp --dport 10001 -s 0/0 -j DROP

Remediation

ActionDetail
PatchUpdate to GeoVision firmware v2.12 (GV-IOBOX_2026-06-01) via official GeoVision security channels
NetworkPlace GV-I/O Box devices behind firewall; block UDP/10001 from untrusted segments
IsolateSegment IoT/physical security devices on dedicated VLAN with no direct internet access

References

CVE-2026-12485.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env python3
"""
Safe Vulnerability Checker for CVE-2026-12485 (GeoVision GV-I/O Box 4E DVRSearch)

This script sends a benign UDP probe to port 10001 to:
1. Detect if the DVRSearch service is running.
2. Check basic response behavior.
3. Perform a **safe** length test (does NOT trigger the overflow).

WARNING:
- This is for authorized testing only on systems you own/control.
- Do not use on production systems without permission.
- The real vulnerability can lead to RCE/crash with longer payloads.
"""

import socket
import sys
import argparse
import time

def send_probe(target_ip, port=10001, timeout=3):
    """Send a safe probe and observe response."""
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.settimeout(timeout)
        
        # Safe probe: CMD_IP_SET like structure with short/normal data
        # Based on public vulnerability details (small payload)
        probe = bytearray([0x00, 0x00, 0x00, 0x01])  # Example command header (CMD_IP_SET guess)
        probe += b"192.168.1.100"  # Short IP
        probe += b"\x00" * 20      # Padding
        
        print(f"[+] Sending safe probe to {target_ip}:{port} ...")
        sock.sendto(probe, (target_ip, port))
        
        try:
            data, addr = sock.recvfrom(2048)
            print(f"[+] Received response ({len(data)} bytes) from {addr}")
            print(f"[+] Service appears active. Response preview: {data[:64]}...")
            return True, data
        except socket.timeout:
            print("[-] No response received (timeout). Service may not be listening or filtered.")
            return False, None
            
    except Exception as e:
        print(f"[-] Error: {e}")
        return False, None
    finally:
        sock.close()

def safe_length_test(target_ip, port=10001, timeout=3):
    """Send incrementally larger but still safe payloads (well below overflow threshold)."""
    print("\n[+] Performing safe length test (non-crashing)...")
    sizes = [50, 100, 200, 400]  # Conservative sizes
    
    for size in sizes:
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            sock.settimeout(timeout)
            
            payload = b"A" * size
            header = bytearray([0x00, 0x00, 0x00, 0x01])
            probe = header + payload
            
            print(f"    Testing payload size: {len(probe)} bytes...")
            sock.sendto(probe, (target_ip, port))
            
            try:
                data, _ = sock.recvfrom(2048)
                print(f"    [+] Size {len(probe)} -> Response received ({len(data)} bytes)")
            except socket.timeout:
                print(f"    [-] Size {len(probe)} -> No response")
            
            time.sleep(0.5)
        except Exception as e:
            print(f"    [!] Error on size {size}: {e}")
        finally:
            sock.close()

def main():
    parser = argparse.ArgumentParser(description="Safe CVE-2026-12485 Checker")
    parser.add_argument("target", help="Target IP address")
    parser.add_argument("-p", "--port", type=int, default=10001, help="UDP port (default: 10001)")
    parser.add_argument("--length-test", action="store_true", help="Run safe length test")
    args = parser.parse_args()

    print("=" * 60)
    print("Safe CVE-2026-12485 (GV-I/O Box 4E DVRSearch) Checker")
    print("=" * 60)
    print(f"Target: {args.target}:{args.port}")
    print("This script does NOT exploit the vulnerability.\n")

    active, _ = send_probe(args.target, args.port)
    
    if active and args.length_test:
        safe_length_test(args.target, args.port)
    
    print("\n" + "=" * 60)
    print("Recommendation:")
    print("- If service responds → Update firmware immediately (GV-IOBOX_2026-06-01).")
    print("- Block UDP/10001 from untrusted sources.")
    print("- Full advisory: https://talosintelligence.com/vulnerability_reports/TALOS-2026-2377")
    print("=" * 60)

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python3 CVE-2026-12485-check.py <target_ip> [--length-test]")
        sys.exit(1)
    main()