
Von einer blanken Platine bis zum Root-Zugriff: Hardware-Hacking eines ZyXEL P-870HN (BCM6368) über UART — CVE-2025-0890 + CVE-2024-40891, auf meiner eigenen Hardware.
Zwei Handyfotos einer unbeschrifteten Router-Platine → serielle Konsole → Auth-Bypass → Root-Shell – Reproduktion der realen, weiterhin ungepatchten Kette CVE-2025-0890 (verstecktes supervisor-Konto) + CVE-2024-40891 (CLI-Befehlsinjektion) auf eigener Hardware.
von damik0 · 2026-08-13 · ein Hardware-Hacking-Walkthrough
📷 PCB photos ─▶ 🔬 chip recon ─▶ 🏷️ model ID ─▶ 📍 find UART (J2)
└─▶ 🔌 serial console ─▶ 🚪 hidden account ─▶ ⛓️ break out of CLI
└─▶ 🐚 root shell ─▶ 🔓 dump + crack every credential
Auf meinem Schreibtisch lag eine x-beliebige Router-Platine. Kein Gehäuse, kein Label, keine Ahnung, was es war. Ausgehend von nichts als zwei Fotos habe ich jeden Chip auf der Platine identifiziert, das genaue Modell bestimmt, den seriellen Header (UART) gefunden, mich eingeklinkt, bin durch ein Werks-Hintertürkonto hineinspaziert, aus einem abgeriegelten Herstellermenü in eine Root-Linux-Shell ausgebrochen und jedes Passwort von dem Gerät gezogen – in unter einer Sekunde geknackt.
Keiner dieser Bugs stammt von mir. Es sind dokumentierte ZyXEL-Probleme, die der Hersteller laut eigener Aussage nicht patchen wird. Worum es in diesem Repo geht, ist das Wie, Ende zu Ende, und die Argumentation hinter jedem Schritt.
Ich habe die ID anhand der Siebdruck-Platinennummer 45-402-000022 und des Barcodes ermittelt und mit TechInfoDepot, der OpenWrt-Hardwaretabelle und der FCC-ID I88P870HN51B abgeglichen:
Warum die Platinennummer der Schlüssel ist, der alles öffnet: ODM-Gateways wie dieses sind Referenzdesigns. Sobald die Siebdruck-Teilenummer zu einer dokumentierten Platine passt, erbt man die Hausaufgaben von jemand anderem – den genauen Flash-Chip, die UART-Position und Pinbelegung, die Standardkonten. Die Identifizierung ist keine Formalie; sie macht aus blindem Sondieren einen gezielten Angriff.
Zuerst eine kleine Komfortsache: Ich habe einen winzigen LAN-Foto-Uploader zusammengebaut (Python-Standardbibliothek, null Abhängigkeiten), damit ich die Platine mit dem Handy abfotografieren konnte und die Bilder direkt auf meinem Rechner landeten. Die halbe Miete einer guten Session ist es, solche Reibungspunkte zu beseitigen.
Ich bin Chip für Chip die hochauflösenden Fotos durchgegangen. Die Gehäusetypen erzählen die Geschichte, bevor man überhaupt die Beschriftungen liest: Das BGA in der Mitte ist das Gehirn, das TSOP-48 ist fast immer paralleler Flash, die kleine Blechkappe mit Koaxial-Pigtail ist das Funkmodul. Der SoC versteckte sich unter einer RF-Abschirmung (für EMV und als Wärmeverteiler), also habe ich die Kappe abgehebelt, um die Markierung darunter zu lesen – ein Broadcom BCM6368.

Die Platine, kartiert: (1) BCM6368-SoC, (2) DDR2-RAM, (3) BCM43222-WLAN, (4) DSL-Leitungsübertrager, (5) Ethernet-Magnetics, (6) interne USB-Header, (7)(8) Platinenmarkierungen, (9) der J2-Konsolen-Header, (10) ein unbestücktes JTAG-Footprint.
Der Siebdruck 45-402-000022 passte exakt zur dokumentierten Platine, und jeder Chip – SoC, Flash, WLAN, die 64 MB RAM – fügte sich Stück für Stück zur -53b-Variante. Jetzt wusste ich nicht nur, was es war, sondern auch, wo sein UART lag und welches Konto mich hineinlassen würde.
Direkt neben dem SoC befand sich ein bestückter 6-Pin-Winkelstecker mit Siebdruck J2 und einer Dreiecksmarkierung für Pin 1. Bestätigt durch die OpenWrt-Seite für das Modell:
115200 8N1, 3,3-V-TTL.

So findet man ein UART, wenn einem kein Wiki die Pinbelegung verrät – der Teil, der zeigt, dass das nicht nur einer Anleitung folgt:
- GND – Durchgang (Piepser) zur Massefläche / Abschirmung, Platine ohne Strom.
- VCC – eine Schiene, die nach dem Einschalten konstant bei ~3,3 V liegt.
- TX – ruht auf High bei ~3,3 V (UART-Markenzustand) und zuckt/flackert sichtbar in dem Moment, in dem das Gerät bootet und sein Log ausspeit. Dieses Flackern ist die Konsole, die spricht.
- RX – normalerweise der ruhige Kandidat: floating oder schwach gepullt, keine Boot-Aktivität.
Und wenn man die Baudrate nicht wüsste?
115200ist die Broadcom-CFE-Standardeinstellung, aber im Blindflug würde man entweder die üblichen Raten durchlaufen (9600 → 115200), bis der Müll zu ASCII wird, oder die schmalste Bitbreite am Oszilloskop messen und1 / trechnen.
Ich habe einen USB-TTL-Adapter (HW-597, PL2303) mit dem Jumper auf 3,3 V verdrahtet. Das ist wichtig: Das UART des BCM6368 ist 3,3-V-TTL, nicht RS-232 (±12 V) – wenn man einen echten seriellen Port oder einen 5-V-Adapter daranhängt, brät man den Pin. Masse zuerst, dann RX/TX gekreuzt, VCC auf Float gelassen, damit nichts die Platine rückwärts mit Strom versorgt. Vor dem Anlegen der Spannung habe ich GND und VCC mit einem Multimeter bestätigt, dann:
screen /dev/ttyUSB0 115200
Eingeschaltet, zugesehen, wie der CFE an den Kernel übergibt, wie BusyBox-init hochkommt, und landete an einem Login-Prompt.
Der Login fiel einem versteckten Werkskonto zum Opfer, das ZyXEL für Endnutzer nie dokumentiert:
user: supervisor
pass: zyad1234
Volle Systemrechte. Das ist der Kern von CVE-2025-0890.
Dieser Login warf mich in eine abgeriegelte Hersteller-CLI (consoled, ein >-Prompt): kein sh, keins der üblichen Linux-Werkzeuge – ein Jail um das eigentliche System. Aber sie bot eine ping-Diagnose an, und dieser Befehl baute sein Argument direkt mit null Bereinigung in einen Shell-String ein. Also habe ich ihm ein Shell-Metazeichen gefüttert:
> ping 127.0.0.1; sh
… und landete in einer Root-BusyBox-Shell (#).
Warum ein Semikolon reicht: Der CLI-Handler macht im Endeffekt
system("ping " + userinput). Das;beendet denping-Befehl und startet einen zweiten –sh–, der stdin/stdout der Konsole erbt, sodass man eine interaktive Shell bekommt. Das Konto war bereits uid 0; die CLI war das Einzige, was zwischen mir und einer echten Shell stand, und unsanitisierte Eingabe riss diese Mauer ein. Eine authentifizierte CLI-Injektion mit dem versteckten Konto zu verketten, ist genau das Muster, das als CVE-2024-40891 erfasst ist.
Mit Root habe ich mir das System und den Flash angesehen:
# cat /proc/version
Linux version 2.6.30 ... (Buildroot 2010.02) #1 Mon Jun 11 2012
# cat /proc/mtd
dev: size erasesize name
mtd0: 004f5000 004f5000 "Physically mapped flash" # 5,197,824 bytes = the whole firmware
Was
/proc/mtddir sagt: Der Flash ist paralleler NOR, speichergemappt – die CPU sieht ihn als flachen Adressbereich (oben bei0xB8000000im MIPS-KSEG1), exponiert als einzelne MTD-Partition. Das sind großartige Nachrichten für einen Dump: NOR liest sich sauber zurück, ganz ohne die Spare-/OOB-Bytes und ECC-Eigenheiten, mit denen man bei NAND kämpft./dev/mtdblock0ist das Firmware-Image.
Dann die Passwörter. Es gibt kein /etc/shadow – die Hashes stehen direkt in /etc/passwd und verwenden uraltes DES-crypt:
supervisor:SuO7vycdWI/rU:0:0:Administrator:/:/bin/sh
support:xoKf506EVkGKw:1:0:Technical Support:/:/bin/sh
user:QWOftoXez8Goo:2:0:Normal User:/:/bin/sh
admin:OJGXQ9dWyb9m2:100:0:Administrator:/:/bin/sh
Ich habe sie gezogen und offline mit John the Ripper geknackt (--format=descrypt). Alle sechs fielen in unter einer Sekunde:
Warum die sofort verglühen: DES-
crypt(3)hat immer nur die ersten 8 Zeichen des Passworts und ein 12-Bit-Salt verwendet, durch 25 Runden DES. Auf einer modernen CPU frisst ein Bitslice-DES-Knacker zig Millionen Kandidaten pro Sekunde – daher fallen triviale Werkspasswörter wieadminodersupportnicht einmal als Arbeit ins Gewicht. Dieses Schema war schon vor Jahrzehnten veraltet; dass es in ausgelieferter Firmware steckt, ist die eigentliche Erkenntnis.
Vier Werkskonten mit Root-Rechten, triviale Passwörter, auf jedem Gerät dieses Modells identisch.
Die ganze Kette in einer Zeile:
PCB photo → ID the SoC → find the UART (J2) → serial console
→ hidden account (F-1) → locked CLI → command injection (F-2)
→ root shell → dump + crack every credential (F-3)
Das habe ich nicht entdeckt. Es ist die Reproduktion öffentlicher und aktuell relevanter Bugs durch physischen Zugriff:
supervisor:zyad1234, auf Legacy-ZyXEL-DSL-CPE. → F-1Diese treffen End-of-Life-Geräte, die ZyXEL laut eigener Aussage nicht mehr patchen wird, und sie wurden bereits in freier Wildbahn ausgenutzt – genau deshalb ist es wichtig, die Mechanik praktisch zu erfassen. Der Wert liegt hier nicht in einem neuen Bug, sondern im kompletten Silicon-to-Shell-Workflow, durchgeführt und dokumentiert.
execve mit Argument-Vektor verwenden, nicht system())./etc/shadow mit einem modernen Hash umstellen (bcrypt / SHA-512-crypt), nicht DES.mtd0 (/dev/mtdblock0, 5.197.824 Bytes) über das eigene WLAN des Routers + nc dumpen und dann mit binwalk entpacken (zu erwarten: CFE-Header + LZMA-komprimierter Kernel + SquashFS-Rootfs + nvram). Vollständige Methode in evidence/dump-methods.md.Platinenanalyse anhand von Fotos (ImageMagick), ein Multimeter, ein USB-TTL-PL2303-Adapter (HW-597) bei 3,3 V, screen für die serielle Konsole (115200 8N1) und John the Ripper (descrypt) für die Hashes. Identifizierung über OpenWrt, TechInfoDepot und die FCC-Datenbank.
Geräteidentifikation
45-402-000022, Flash MX29LV640EBTI-70G)Schwachstellen
supervisor-KontoHardware & Technik
Werkzeuge
Durchgeführt auf meiner eigenen Hardware, ohne Netzwerkverbindung, keine Drittsysteme beteiligt. Die Bugs sind öffentlich dokumentiert und oben zitiert. Wofür ich mit meinem Namen stehe, ist die durchgängige Hardware-Hacking-Methode und ihre Ausführung – nicht die Entdeckung der Schwachstellen.
| Modell | ZyXEL P-870HN-53b – VDSL2/ADSL2+-WLAN-Gateway, hergestellt von MitraStar |
| Zeitraum | ~2013 (Datumsangaben deuten auf KW 21 / 2013); ein von einem ISP verteiltes Gerät |
| SoC | Broadcom BCM6368UKPBG – Dual-Core-MIPS (BMIPS4350), ~400 MHz |
| RAM | 2× Winbond W9425G6JH-5 – je 256 Mbit DDR2 ×16 = 64 MB auf einem 32-Bit-Bus |
| Flash | Macronix MX29LV640EBTI-70G – 8 MB paralleler NOR, TSOP-48 |
| WLAN | Broadcom BCM43222 (802.11n; Dual-Band-Silizium, nur mit 2,4 GHz verdrahtet) |
| DSL-AFE | Broadcom BCM6302 |
| Firmware | Linux 2.6.30 + BusyBox v1.00, Broadcom-CFE-Bootloader (gebaut 2012-06-11) |
| Pin | Signal |
|---|
| 1 | VCC 3,3 V | nicht anschließen |
| 2 | Tx | → Adapter RX |
| 3 | Rx | → Adapter TX |
| 4 | GND | → Adapter GND |
| 5 | NC |
| Konto | Passwort | UID | GID | Rechte |
|---|
| supervisor | zyad1234 | 0 | 0 | root |
| support | support | 1 | 0 | Root-Gruppe |
| user | user | 2 | 0 | Root-Gruppe |
| admin | admin | 100 | 0 | Root-Gruppe |
| nobody | zyad1234 | 99 | 99 | ftp |
| # | Befund | CWE | Schweregrad |
|---|
| F-1 | Versteckte Werkskonten mit Root-Rechten (supervisor, support, user, admin) – hartkodierte Zugangsdaten, auf jedem Gerät identisch. | CWE-798 | Hoch |
| F-2 | Authentifizierte Befehlsinjektion in der CLI-Diagnose ping → Ausbruch in eine Root-Shell, die die Rechtegrenze der CLI überspringt. | CWE-78 | Hoch |
| F-3 | Schwache Speicherung von Zugangsdaten – DES-crypt-Hashes in /etc/passwd (kein Shadow) → sofortiges Offline-Knacken. | CWE-916 / CWE-256 | Mittel |