Les caméras Puwell testées exposent un service TCP propriétaire accessible sur le port 23456, utilisé pour le contrôle à distance de l'équipement. L'analyse de ce protocole montre qu'aucun mécanisme d'authentification ou de contrôle d'accès n'est mis en œuvre avant le traitement des commandes reçues. En conséquence, tout client capable d'établir une connexion avec ce service peut interagir directement avec l'appareil et invoquer les fonctionnalités exposées par le protocole.
Tout attaquant en mesure d'établir une connectivité réseau avec l'équipement (par exemple depuis le même réseau local ou via le mécanisme de connectivité pair à pair du constructeur lorsqu'il est activé - UDP Hole Punching) peut communiquer directement avec le service TCP propriétaire sans disposer d'identifiants valides.
Le protocole traite les commandes privilégiées sans vérifier l'identité du client ni l'état de sa session. Il est ainsi possible de :
L'exploitation de cette faiblesse permet à un attaquant non authentifié d'accéder à l'ensemble des fonctionnalités exposées par le protocole de contrôle propriétaire et d'en prendre le contrôle.
L'analyse du firmware par rétro-ingénierie a permis de reconstituer la structure du protocole à partir des chaînes de débogage et des routines de traitement des paquets. Ces éléments révèlent le format des messages, la logique de traitement des codes d'opération (opcodes) ainsi que le décodage des données, rendant possible la reconstruction de messages conformes au protocole.
Les extraits suivants illustrent la manière dont les champs du protocole et les gestionnaires de commandes ont été identifiés :
Figure 1 : Code décompilé montrant le traitement des opcodes
Figure 2 : Code décompilé montrant l'analyse du mode du protocole
Figure 3 : Fonction GPIO responsable du contrôle des moteurs de panoramique et d'inclinaison
Figure 4 : Routine de validation décompilée montrant le traitement des commandes de panoramique et d'inclinaison
Le format reconstitué des paquets est présenté ci-dessous :
Figure 5 : En-tête binaire du protocole
Le champ Session présent dans l'en-tête du protocole n'est jamais vérifié et n'est associé à aucune session authentifiée. Par conséquent, n'importe quelle valeur est acceptée, sans qu'il soit nécessaire de négocier ou d'obtenir un identifiant de session valide avant l'envoi de commandes privilégiées.
La preuve de concept Python ci-dessous montre que le service TCP exposé sur le port 23456 accepte et traite des messages conformes au protocole sans nécessiter d'authentification ni d'établissement préalable d'une session.
Codeimport socket
import struct
TARGET_IP = "192.168.2.42"
SESSION = 0xbadc0de0
FIELD = 0x02963ED5
OP_HEARTBEAT = 0x0001
def build_packet(opcode, payload):
header = struct.pack("<IIII", 0xFFEEDDCC, opcode, SESSION, len(payload))
return header + payload
payload = struct.pack("<II", 0, FIELD) + b"\x00" * 20
packet = build_packet(OP_HEARTBEAT, payload)
sock = socket.create_connection((TARGET_IP, 23456))
sock.sendall(packet)
response = sock.recv(1024)
print(response.hex())
sock.close()
Le paquet transmis respecte le format du protocole propriétaire implémenté par l'appareil.
La réception d'une réponse valide confirme que l'équipement traite les messages du protocole sans authentifier le client ni vérifier l'identifiant de session fourni. Une fois la communication établie, il est possible d'envoyer d'autres codes d'opération afin d'accéder aux fonctions privilégiées du dispositif, notamment le contrôle du panoramique et de l'inclinaison, des LED, de la lecture audio ainsi que le redémarrage de l'appareil. Ce comportement démontre l'absence totale de mécanismes d'authentification et de contrôle d'accès dans l'implémentation du protocole.