Chapter 11
ファームウェア抽出とデバッグポート
この章がなぜ必要なのか——攻撃は、ほぼ必ずここから始まるから.
09 章のサイドチャネルも、10 章のフォールトも、 まずファームウェアを読んで、狙う場所を特定するところから始まる。
そして実務では——ファームウェアを読まれた時点で、 ハードコードされた鍵やパスワードが出てきて、それで終わることが非常に多い。
ここを塞ぐことが、費用対効果の最も高い対策である。
この章で使う既出の用語(定義は各リンク先). 数万円(01 章 2 節)、物理攻撃(04 章 6 節)、OTFDEC(06 章 6 節)、Secure(07 章 3 節)、TrustZone(07 章 2 節)、サイドチャネル(07 章 8 節)、フォールト(07 章 8 節)、両方(07 章 3 節)、必要(09 章 6 節)
1. ファームウェアはどこから漏れるか
デバッグポートとファームウェア抽出経路
各経路をクリックすると、攻撃の手順と対策が表示される。
| 経路 | 難度 | 必要なもの |
|---|---|---|
| メーカーの公開ファームウェア | ★(最も簡単) | ブラウザ |
| OTA の通信を傍受 | ★ | ネットワーク解析 |
| UART コンソール | ★ | USB シリアル変換(数百円) |
| SWD / JTAG | ★★ | デバッガ(数千円) |
| 外付け SPI/NAND フラッシュを読む | ★★ | クリップ、プログラマ(数千円) |
| ISP / ブートローダモード(工場書き込みモード。6 節) | ★★ | ベンダのツール |
| 保護をグリッチで突破 | ★★★ | グリッチ装置(数万円、10 章) |
| チップ開封 + プロービング | ★★★★★ | 専用ラボ(数百万円〜) |
上から 5 つは、すべて「設定ミス」で開く.
つまり追加の部品コストをかけずに塞げる。 ここを塞がずに暗号アクセラレータの議論をしても意味がない。
2. 経路 1: 公開ファームウェアと OTA
最も見落とされる経路である。
| 状況 | 問題 |
|---|---|
| サポートサイトで更新ファイルを配布 | 誰でもダウンロードして解析できる |
| OTA が平文 HTTP | 通信を傍受すれば手に入る |
| OTA が暗号化されていない | TLS で運ばれても、ファイル自体は平文 |
# 攻撃者がやること(イメージ)
$ binwalk firmware.bin # 中身の構造を調べる
$ binwalk -e firmware.bin # ファイルシステムを展開
$ strings firmware.bin | grep -i -E 'key|passwd|secret|token|BEGIN'
$ grep -r "AWS" extracted/ # クラウドの認証情報を探す対策:
| 対策 | 内容 | 章 |
|---|---|---|
| OTA イメージを暗号化する | 機器だけが復号できる形にする | 13 |
| 機器ごとに違う鍵で暗号化 | 難しいが、可能な場合もある | 13 |
| とにかく秘密を埋め込まない | 最も重要。鍵は実行時にプロビジョニングされたものを使う | 06, 12 |
「暗号化すれば安全」ではない.
OTA イメージを暗号化しても、全機器が同じ鍵で復号するなら、 1 台から鍵を取れば全イメージが復号できる。
だから「イメージの暗号化」は時間稼ぎであって、根本対策ではない。 根本対策は「ファームウェアに秘密を含めないこと」である。
秘密(機器固有鍵、証明書)は、 工場でのプロビジョニング(12 章)か、初回起動時の生成で入れる。 ファームウェアイメージには入れない。
3. 経路 2: UART コンソール
基板を見ると、4 ピンのパターン(VCC・GND・TX・RX)がよく残っている。
- 基板のテストパッドやピンヘッダを探す
- USB シリアル変換を繋ぎ、ボーレートを総当たりする(9600〜921600)
- 起動ログが流れてくる → ブートローダの種類、カーネル、ファイルシステム構成が分かる
- Enter を押す → シェルプロンプトが出ることがある
- ブートローダで起動を中断 → 起動引数を書き換えて
init=/bin/sh
| よくある問題 | 対策 |
|---|---|
| 起動ログに詳細情報が出る | 量産ビルドではログレベルを下げる |
| シェルが出る | 量産ビルドではコンソールを無効化する |
| パスワードがあるが弱い/共通 | 機器固有にするか、そもそも無効化する |
| ブートローダで停止できる | ブートローダの対話機能を無効化する |
| パッドが残っている | 量産基板ではパッドを削除する、または結線を切る |
/* ビルド設定で切り分ける */
#ifdef PRODUCTION_BUILD
#define DEBUG_CONSOLE_ENABLED 0
#define LOG_LEVEL LOG_ERROR
#else
#define DEBUG_CONSOLE_ENABLED 1
#define LOG_LEVEL LOG_DEBUG
#endif「デバッグ機能をコンパイル時に除去する」ことが重要である.
実行時のフラグで無効化するだけでは、 コードが残っているのでグリッチや脆弱性で有効化されうる。
量産ビルドには、そもそもコードを含めない。 リンカマップを見て、デバッグ用シンボルが残っていないか確認するとよい。
4. 経路 3: SWD / JTAG
最も直接的な経路である。 デバッガを繋げば、
- フラッシュ全体を読み出せる
- RAM の内容を読める(鍵が乗っている)
- CPU を停止・ステップ実行できる
- レジスタを書き換えられる
保護の方法
| 方法 | 内容 |
|---|---|
| 読み出し保護(RDP / CRP / FSEC) | フラッシュ読み出しを禁止する(06 章) |
| デバッグポートの無効化 | ヒューズ/オプションバイトで完全に閉じる |
| 認証付きデバッグ (Secure Debug) | 鍵を持つ者だけがデバッグを開ける |
| 物理的な切断 | 量産基板でパターンを切る、テストパッドを削除する |
認証付きデバッグ
閉じるか開けるかの二択ではなく、「認証すれば開く」という第 3 の道である。
| 標準・実装 | 内容 |
|---|---|
| Arm ADAC (Authenticated Debug Access Control) | Arm が定めた認証デバッグの仕様 |
| NXP Debug Authentication | LPC55 / i.MX RT で提供 |
| ST Debug Authentication | STM32H5 / U5 などで提供 |
| Silicon Labs Secure Debug Unlock | Secure Vault の機能 |
| Nordic | 品種による |
認証付きデバッグは、RMA(返品分析)の切り札である.
14 章で詳しく扱うが、 「量産品を完全にロックすると、故障解析ができない」という深刻な問題がある。
認証付きデバッグなら——
- 出荷時は閉じている
- メーカーだけが持つ鍵で開けられる
- 開けたときに鍵を自動消去する設定にもできる(機密は守られる)
これがあるかどうかは、SoC 選定の重要な基準である。
5. 経路 4: 外付けフラッシュ
MCU がどれだけ堅牢でも、外付けフラッシュは別のチップである。
- SPI フラッシュ(W25Qxx、MX25Lxx など)を基板上で特定する
- SOIC クリップ(基板に載ったままのチップへ上から挟んで配線を取り出す治具)を付けてその場で読む、またはホットエアで外してプログラマで読む
- 数分でフルダンプが取れる
| 対策 | 効果 |
|---|---|
| フラッシュ暗号化(06 章) | 内容が読めない。鍵は MCU 内にある |
| オンザフライ復号(OTFDEC / PRINCE / BEE / Flash Encryption) | XIP でも暗号化できる |
| 重要な部分を内部フラッシュに置く | 最も確実 |
| BGA パッケージのフラッシュ | 若干難しくなるが、外せる |
バスの盗聴も可能である.
フラッシュを外さなくても、SPI バスにロジックアナライザを繋げば 転送内容が読める。XIP で実行していれば、実行中のコードがそのまま流れる。
だから「起動時だけ復号する」のでは足りない。 常時暗号化されたまま転送される必要がある。 これがオンザフライ復号エンジンの役割である。
6. 経路 5: ISP / ブートローダモード
多くの MCU が、工場書き込み用の ROM ブートローダを持っている。 基板に実装したまま外部から書き込める仕組みなので ISP(In-System Programming)と呼ばれる。
| 経路 | 例 |
|---|---|
| UART ブートローダ | BOOT ピンを引いて起動すると、UART から書き込める |
| USB DFU(Device Firmware Upgrade) | USB 経由でファームウェアを書き込める |
| SDP(Serial Download Protocol) | NXP i.MX の ROM 機能 |
これらは「書き込み」だけでなく「読み出し」もできる場合がある。
| 対策 | 内容 |
|---|---|
| ROM ブートローダを無効化 | OTP / オプションバイトで無効にする |
| ブートソースを固定 | 内部フラッシュからしか起動しないよう固定 |
| BOOT ピンを固定 | 基板でプルダウン/プルアップして固定する |
| 読み出し保護と連動 | 保護レベルが上がると ROM ローダの読み出しも禁止される(品種による) |
必ずデータシートで「保護レベルと ROM ブートローダの関係」を確認すること.
「フラッシュ読み出し保護をかけたのに、 ROM ブートローダ経由では読めた」という事故が起こりうる。
特に、保護をかけても「消去」はできる設計になっていることが多い。 消去は攻撃者にとって直接の利益にならないが、 消去 → 保護解除 → 自分のコードを書き込んで、外付けフラッシュを読ませる という 2 段構えの攻撃が成立する場合がある。
7. RAM に残る秘密
フラッシュを守っても、実行中の RAM には平文の鍵が乗っている。
| 攻撃 | 内容 |
|---|---|
| デバッガで RAM を読む | 上記の SWD/JTAG 対策で防ぐ |
| コールドブート攻撃 | 電源断直後の DRAM/SRAM には内容が残る。冷却すると保持時間が伸びる |
| リセット後の SRAM 読み出し | リセットでは SRAM がクリアされない MCU がある |
対策:
/* 使い終わった鍵は必ず消す([08 章](08_暗号エンジンと乱数.md#落とし穴-2-dma-と共有バス)) */
mbedtls_platform_zeroize(session_key, sizeof(session_key));
/* リセット時・起動時に SRAM をクリアする */
void SystemInit(void) {
extern uint32_t _sram_start, _sram_end;
for (uint32_t *p = &_sram_start; p < &_sram_end; p++) *p = 0;
}| ハードウェア対策 | 内容 |
|---|---|
| タンパー検出時の SRAM 消去 | 筐体開放などを検出したら即座に消す |
| バックアップレジスタの自動消去 | ST の tamper 機能など |
| TrustRAM(Microchip SAM L11) | スクランブル格納、サイレントアクセス、タンパ時消去 |
| セキュア SRAM | TrustZone で Secure 属性にした領域 |
8. ファームウェアの解析を難しくする
塞ぎきれない前提で、解析コストを上げるという考え方もある。
| 手法 | 効果 | 注意 |
|---|---|---|
| シンボル・デバッグ情報の除去 | 必須。関数名が消えるだけで解析コストが数倍になる | strip、-g を外す |
| 文字列の暗号化 | strings で情報が出なくなる | 実行時に復号するコードが要る |
| コード難読化 | 逆コンパイルを困難にする | 商用ツールが必要。デバッグが難しくなる |
| 制御フロー平坦化 | 静的解析を困難にする | 性能が落ちる |
難読化は「セキュリティ」ではなく「時間稼ぎ」である.
Security through obscurity(隠すことによる安全)は原則として避けるべきである。 暗号鍵や認証の強度を難読化に依存してはいけない。
ただし、正しい対策の上に追加で載せる分には価値がある。 特にシンボルの除去は、コストゼロで効果が大きいので必ずやること。
# リリースビルドでは必ず arm-none-eabi-strip --strip-all firmware.elf # マップファイルを確認して、デバッグ用シンボルが残っていないか見る
9. 出荷前チェックリスト
この章の内容は、そのままチェックリストになる。
| # | 確認項目 |
|---|---|
| 1 | SWD / JTAG が無効化されているか(または認証付きデバッグに設定されているか) |
| 2 | 読み出し保護が有効か。レベルは適切か |
| 3 | ROM ブートローダ/ISP が無効化されているか |
| 4 | UART コンソールが無効化されているか(コード自体が入っていないか) |
| 5 | デバッグ用のコマンド・バックドアが除去されているか |
| 6 | 外付けフラッシュが暗号化されているか |
| 7 | ファームウェアに秘密(鍵・パスワード・トークン)が埋まっていないか |
| 8 | シンボル・デバッグ情報が除去されているか |
| 9 | 公開する更新ファイルから秘密が読めないか |
| 10 | RAM の秘密が使用後に消去されているか |
| 11 | テストパッド/ピンヘッダが量産基板から削除されているか |
| 12 | 保護設定がフォールト耐性を持つか(10 章) |
7 番目の確認方法.
# 出荷イメージに対して、必ず実行する strings firmware.bin | grep -i -E 'password|passwd|secret|api[_-]?key|token|BEGIN (RSA|EC|PRIVATE)' binwalk -E firmware.bin # エントロピーを見る(高エントロピー領域 = 鍵かもしれない)CI に組み込んで、毎ビルドで自動チェックすること。 人間のレビューでは必ず見落とす。
より本格的には、シークレットスキャナ(gitleaks、trufflehog など)を ソースとビルド成果物の両方に対して回す。
10. この章のまとめ
| ポイント | 内容 |
|---|---|
| 攻撃の起点 | ほぼすべての物理攻撃がファームウェア解析から始まる |
| 最も安い経路 | 公開ファームウェア、UART、SWD、外付けフラッシュ。設定で塞げる |
| 根本対策 | ファームウェアに秘密を埋め込まない。イメージ暗号化は時間稼ぎ |
| UART | 量産ビルドからコードごと除去する。実行時フラグでは不十分 |
| SWD / JTAG | 無効化するか、認証付きデバッグ(Arm ADAC など)を使う |
| 認証付きデバッグ | RMA 対応の切り札。選定基準に入れるべき |
| 外付けフラッシュ | 外せば数分で読める。オンザフライ復号が必要 |
| ROM ブートローダ | 無効化する。「保護してもブートローダから読めた」事故に注意 |
| RAM の秘密 | 使用後に zeroize。起動時に SRAM クリア |
| 難読化 | セキュリティではなく時間稼ぎ。ただしシンボル除去は必須 |
| 検証 | CI で strings とシークレットスキャンを自動化する |
ここまでで第 III 部は終わりである。 次章から第 IV 部——機器の一生を通した鍵と状態の管理に入る。