
むき出しのPCBからrootまで: UART経由でZyXEL P-870HN (BCM6368) をハードウェアハッキング — CVE-2025-0890 + CVE-2024-40891、自分のハードウェア上で。
ラベルのないルーター基板のスマホ写真2枚 → シリアルコンソール → 認証バイパス → rootシェル — 私が所有するハードウェア上で、実在し、いまだパッチ未適用の連鎖 CVE-2025-0890(隠しsupervisorアカウント)+ CVE-2024-40891(CLIコマンドインジェクション)を再現する。
damik0 著 · 2026-08-13 · ハードウェアハッキングのウォークスルー
📷 PCB photos ─▶ 🔬 chip recon ─▶ 🏷️ model ID ─▶ 📍 find UART (J2)
└─▶ 🔌 serial console ─▶ 🚪 hidden account ─▶ ⛓️ break out of CLI
└─▶ 🐚 root shell ─▶ 🔓 dump + crack every credential
机の上に無造作に置いてあった正体不明のルーター基板。筐体もなく、ラベルもなく、何なのかもわからない。写真2枚だけを手がかりに、PCB上のすべてのチップを読み取り、正確なモデルを特定し、シリアル(UART)ヘッダーを見つけて接続し、工場出荷時のバックドアアカウントから侵入し、ロックされたベンダーメニューを脱出してroot Linuxシェルを入手し、そのボックスからすべてのパスワードを引き出した — クラックは1秒未満。
これらの脆弱性はいずれも私が発見したものではない。ベンダーがパッチを当てないと明言している、文書化済みのZyXELの問題だ。このリポジトリのテーマは、その方法をエンドツーエンドで、各ステップの判断根拠とともに示すことだ。
シルクスクリーンの基板番号 45-402-000022 とバーコードから型番を特定し、TechInfoDepot、OpenWrtのハードウェア表、FCC ID I88P870HN51B と照合しました:
| モデル | ZyXEL P-870HN-53b — VDSL2/ADSL2+ WiFiゲートウェイ、MitraStar製 |
| 年代 | 約2013年(デートコードは2013年第21週を示す); ISP配布ユニット |
| SoC | Broadcom BCM6368UKPBG — デュアルコアMIPS(BMIPS4350)、約400 MHz |
| RAM | Winbond W9425G6JH-5 ×2 — 各256 Mbit DDR2 ×16 = 32ビットバス上で64 MB |
| Flash | Macronix MX29LV640EBTI-70G — 8 MBパラレルNOR、TSOP-48 |
| WiFi | Broadcom BCM43222(802.11n; デュアルバンド対応シリコン、2.4 GHzのみ配線) |
| DSL AFE | Broadcom BCM6302 |
| ファームウェア | Linux 2.6.30 + BusyBox v1.00、Broadcom CFEブートローダー(2012-06-11ビルド) |
基板番号がすべてを解き明かす鍵となる理由: この種のODMゲートウェイはリファレンスデザインです。シルクスクリーンの部品番号が文書化された基板と一致すれば、先人が済ませた宿題 — 正確なフラッシュチップ、UARTの位置とピン配置、デフォルトアカウント — をそのまま利用できます。型番の特定は形式的な作業ではなく、手当たり次第のプロービングを標的型攻撃へと変えるものなのです。
まず小さなQoL改善から: スマホで基板を撮影し、その写真が直接マシンに転送されるようにする小さなLAN写真アップローダー(Python標準ライブラリのみ、依存ゼロ)を即席で作りました。良いセッションの半分は、こうした摩擦を取り除くことにあります。
高解像度の写真からチップを1つずつ読み取っていきました。パッケージの種類だけで、刻印を読む前から中身が見えてきます: 中央のBGAが頭脳、TSOP-48はほぼ間違いなくパラレルフラッシュ、同軸ケーブルの付いた小さなキャンは無線部です。SoCはRFシールド(EMI対策とヒートスプレッダーを兼ねる)の下に隠れていたため、キャンを外して下の刻印を読むと — Broadcom BCM6368 でした。

基板のマッピング: (1) BCM6368 SoC、(2) DDR2 RAM、(3) BCM43222 WiFi、(4) DSLライントランス、(5) Ethernetパルストランス、(6) 内部USBヘッダー、(7)(8) 基板刻印、(9) J2コンソールヘッダー、(10) 未実装のJTAGフットプリント。
シルクスクリーンの 45-402-000022 は文書化された基板と完全に一致し、SoC、フラッシュ、WiFi、64 MBのRAMまで、すべてのチップが**-53b**バリアントと一つずつ一致しました。これで何なのかが分かっただけでなく、UARTがどこにあり、どのアカウントで入れるのかも分かりました。
SoCのすぐ隣に、部品実装済みの6ピン直角ヘッダーがあり、シルクスクリーンで J2 と印字され、三角形マークがピン1を示していました。OpenWrtのこのモデルのページで確認:
| ピン | 信号 | |
|---|---|---|
| 1 | VCC 3.3V | 接続しない |
| 2 | Tx | → アダプターRXへ |
| 3 | Rx | → アダプターTXへ |
| 4 | GND | → アダプターGNDへ |
| 5 | NC |
115200 8N1、3.3V TTL。

ピン配置を教えてくれるWikiがない場合のUARTの見つけ方 — ここで示したいのは、これが単にレシピに従うだけの話ではないということです:
- GND — 未通電の状態で、グランドプレーン/シールドへの導通(ビープ音)を確認。
- VCC — 通電すると約3.3 Vで安定するレール。
- TX — 約3.3 Vでハイレベルにアイドリング(UARTのマーク状態)し、デバイスが起動してログを吐き出し始めた瞬間に目に見えてディップ/ちらつきが発生。そのちらつきこそがコンソールの声です。
- RX — 通常はおとなしい方: フローティングか弱いプルで、起動時の活動はなし。
ボーレートが分からない場合は?
115200はBroadcom CFEのデフォルトですが、手探りなら一般的なレート(9600 → 115200)をスイープして文字化けがASCIIに変わるポイントを探すか、オシロスコープで最小ビット幅を測定して1 / tを計算します。
USB-TTLアダプター(HW-597、PL2303) を、ジャンパーを3.3Vに設定して配線しました。これは重要です: BCM6368のUARTは3.3V TTLであり、RS-232(±12V)ではありません — 本物のシリアルポートや5Vアダプターを接続するとピンを焼きます。まずGNDを接続し、RX/TXはクロス接続、VCCはフローティングのままにして基板への逆給電を防ぎます。通電前にマルチメーターでGNDとVCCを確認し、その後:
screen /dev/ttyUSB0 115200
電源を入れると、CFEがカーネルへ引き継ぐ様子、BusyBox init が立ち上がる様子を観察し、ログインプロンプトに到達しました。
ログインは、ZyXELがエンドユーザー向けには一切文書化していない隠しファクトリーアカウントで突破できました:
user: supervisor
pass: zyad1234
システム全体に対する権限を持つアカウントです。これがCVE-2025-0890の核心です。
そのログインで辿り着いたのはロックダウンされたベンダーCLI(consoled、>プロンプト)でした: shもなく、通常のLinuxツールも何もない — 実システムを包む牢獄です。ただし、ping診断コマンドが使え、そのコマンドは引数を一切サニタイズせずにシェル文字列へ直接埋め込んでいました。そこでシェルのメタキャラクターを送り込みました:
> ping 127.0.0.1; sh
…すると、rootのBusyBoxシェル(#)に落ちました。
セミコロン1つで十分な理由: CLIハンドラーは
system("ping " + ユーザー入力)と同等のことを行います。;はpingコマンドを閉じて2つ目のコマンド —sh— を開始し、これはコンソールのstdin/stdoutを引き継ぐため、対話型シェルが得られます。アカウントは既にuid 0でした。実シェルと私を隔てていたのはCLIだけであり、サニタイズされていない入力がその壁を打ち壊しました。隠しアカウントに認証済みCLIインジェクションを連鎖させる、まさにそのパターンがCVE-2024-40891として追跡されています。
rootを手に入れたので、システムとフラッシュを調べました:
# 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
/proc/mtdが教えてくれること: このフラッシュはパラレルNOR、メモリマップドです — CPUはこれをフラットなアドレス範囲(MIPS KSEG1の0xB8000000付近)として認識し、単一のMTDパーティションとして公開します。これはダンプにとって朗報です: NORはNANDで苦労するスペア領域/OOBバイトやECCの不整合なしにクリーンに読み出せます。/dev/mtdblock0こそがファームウェアイメージです。
次はパスワードです。/etc/shadow は存在せず — ハッシュは古のDES cryptで /etc/passwd に直接置かれていました:
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
これらを取り出し、John the Ripper(--format=descrypt)でオフラインクラックしました。6つすべてが1秒未満で破られました:
| アカウント | パスワード | UID | GID | 権限 |
|---|---|---|---|---|
| supervisor | zyad1234 | 0 | 0 | root |
| support | support | 1 | 0 | rootグループ |
| user | user | 2 | 0 | rootグループ |
| admin | admin | 100 | 0 | rootグループ |
| nobody | zyad1234 | 99 | 99 | ftp |
なぜこれらが瞬時に消え去るのか: DES
crypt(3)はパスワードの最初の8文字と12ビットのソルトしか使わず、25ラウンドのDESを実行します。現代のCPUではビットスライスDESクラッカーが毎秒数千万の候補を処理するため、adminやsupportのような単純なファクトリーパスワードは作業としてすら認識されません。この方式は数十年前に時代遅れになっています; 出荷時ファームウェアにこれが残っていること自体が本当の発見です。
ルートレベルの権限を持つファクトリーアカウントが4つ、パスワードはどれも単純で、このモデルの全ユニットで同一です。
| # | 発見事項 | CWE | 深刻度 |
|---|---|---|---|
| F-1 | ルート権限を持つ隠しファクトリーアカウント(supervisor、support、user、admin)— ハードコードされた認証情報、全ユニットで同一。 | CWE-798 | 高 |
| F-2 | CLIのping診断における認証済みコマンドインジェクション → CLIの権限境界を飛び越えてrootシェルへ脱出。 | CWE-78 | 高 |
| F-3 | 脆弱な認証情報の保存 — /etc/passwd 内のDES cryptハッシュ(shadowなし)→ 即座にオフラインクラック可能。 | CWE-916 / CWE-256 | 中 |
連鎖全体を1行で表すと:
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)
これらはいずれも私が発見したものではありません。物理アクセスによる、公知かつ現在も関連性のあるバグの再現です:
supervisor:zyad1234 を含む。→ F-1これらはZyXELが修正しないと明言したEOL機器を標的としており、実環境での悪用も確認されています — だからこそ、その仕組みを実際に手を動かして理解することが重要なのです。ここでの価値は新しいバグではなく、シリコンからシェルに至る完全なワークフローを実行し、文書化したことにあります。