きちんと閉まらないドアは役に立たない Part1

今回のブログは、広く利用されているアクセス制御システムの脆弱性の発見に焦点を当てたマルチパート技術シリーズの第1回目です。ターゲットの取得からエクスプロイトに至るプロセスの調査過程について紹介する内容です。ベンダーと製品を選択から始め、ハードウェアハッキングの技術まで掘り下げていきます。


エグゼクティブサマリー

重要インフラは、グローバルなインフラ全体の基幹です。国家主体の攻撃者にとって紛れもなく魅力的なターゲット領域であり、時として許しがたいほど脆弱です。ここ数年だけを振り返っても、多くの事例がそれを証明しています。パイプライン、エネルギー網、水処理システム、通信事業者などに対するサイバー攻撃が大きく報道され、大胆不敵な攻撃者が世界中で増えていることが強調されています。

アクセス制御システムはデジタルと物理の領域を隔てる数少ない障壁の1つですが、機密性の高い資産の保護にあたっては過信されがちで、独特な攻撃経路になっています。産業用制御システム(ICS)やビルディングオートメーションシステム(BAS)に通じるこの攻撃経路を、研究者も敵対者も見落としてきました。このような隙があったので、このエリアの調査に取り組むことを決めました。

このプロジェクトにおける調査の結果、当時の最新バージョンのファームウェアに8つのユニークな脆弱性があり、このうち4つは認証なしのリモートコード実行だったことを発見し、責任ある開示に踏み切りました。以下の表は、調査結果を整理したものです。

CVE 詳細概要 Mercury ファームウェアのバージョン CVSSスコア
CVE-2022-31479

未認証のコマンドインジェクション

<=1.291 ベース 9.0、テンポラル 8.1
CVE-2022-31480

未認証のDoSDenial-of-Service

<=1.291 ベース 7.5、テンポラル 6.7
CVE-2022-31481

未認証のリモートコード実行

<=1.291 ベース 10.0、テンポラル 9.0
CVE-2022-31486

認証付きコマンドインジェクション

<=1.291 ベース 9.1、テンポラル 8.2
CVE-2022-31482

未認証のDoSDenial-of-Service

<=1.265 ベース 7.5、テンポラル 6.7
CVE-2022-31483

認証された任意のファイルの書き込み

<=1.265 ベース 9.1、テンポラル 8.2
CVE-2022-31484

未認証のユーザーによる改ざん

<=1.265 ベース 7.5、テンポラル 6.7
CVE-2022-31485

未認証の情報詐称

<=1.265 ベース 5.3、テンポラル 4.8

ターゲット選定

どんな攻撃でも、最初に重要になるのはエントリーポイントです。ファイアウォールや高性能のルーターをロックダウンすると、ネットワークに接続された物理的なアクセス制御システムをつい見落としてしまいます。IBM2021年に行った調査によると、物理的なセキュリティ侵害の平均コストは354万ドルで、侵害を特定するのには平均223日かかるとされています。そこで、Trellixのチームは、物理的なアクセス制御を促進するシステムに着目しました。

これまでICS/IoTの領域でデバイスを調査したことはありましたが、アクセス制御は比較的新しい攻撃経路です。重要度の高いターゲット候補をリストアップしていく過程で、Carrierブランドで広く知られるLenelS2を見つけました。同社は、教育、不動産、医療、運輸などさまざまな業界でアクセス制御システムをグローバルに展開しており、連邦政府や州政府の施設での使用も認可されているので目に留まったのです。注目したのは、FIPS201認証を取得したアクセス制御ボードのラインアップの政府の使用が認可され、APL(承認済み製品リスト)に掲載されていることです。(図1

図 1. 米国政府での使用が承認された LNL-4420

図1. 米国政府での使用が承認された LNL-4420

(図1 抄訳)
Lenel
社のOnGuard®システム 米国連邦政府での使用が承認される
ピッツフォード(米ニューヨーク州)2018年4月2日 高度なセキュリティシステムのリーディングプロバイダーであるLenelは、認証を組み込んだ新しい同社のLNL-4420インテリジェントシステムコントローラーが、米国連邦政府承認を取得したことを発表しました。LenelのLNL-4420コントローラーは、Federal Identity, Credentialing and Access Management(FICAM)ソリューションプログラムにおける厳格なセキュリティ脆弱性テストと相互運用性テストを通過し、米国共通役務庁(General Services Administration)の承認製品リストに掲載されています。FICAMは、連邦政府のシステムや施設が、正しい人が、正しい時に、正しい理由で使用されることを保証するために設計された一連のセキュリティ規律です。Lenelは、United Technologies(NYSE:UTX)のユニットの1つであるUTC Climate, Controls & Security(CCS)の一員です。

上の文章を読むとセキュリティ研究者はこう考えるものです。

セキュリティ研究者が見る

私たちが関心を持ったのは、この認証が何を意味するのか、です。それは信頼に値するものなのか? 政府をはじめとする消費者は、これらの「厳格なセキュリティ」テストをどの程度信頼しているのか?これを解明せずにはいられなかったのです。最終的な開示プロセスで、この製品は物理的なアクセスセキュリティの認証を意図したものであり、サイバーセキュリティの検証を意図したものではないことがわかりました。だからといって、私たちの関心は基盤となるコントローラーのセキュリティ機能のテストにあり、全体的なアプローチとモチベーションは変わりませんでした。

ターゲット選定とは

このシリーズで取り上げたLNL-4420コントローラーはLenelS2の主力製品でしたが、最近「生産終了」となり、ほぼ同機種のX4420に置き換えられました。このコントローラーは、今回公表したすべての問題に対して脆弱性がある9つのコントローラーのうちの1つです。このパネルは64のダウンストリームデバイスを制御することができます。典型的なものはカードアクセスリーダーのインターフェースモジュールです。96MBのフラッシュメモリを搭載し、イーサーネットでネットワークに接続できます。OnGuardと呼ばれる管理ソフトウェアと統合され、ASHRAE-BACNETプロトコルを使用したビルディングオートメーションに用途を拡張することができます。全体的に非常にわかりやすく、ビルの入退室管理に特化した作りになっています。

製造メーカーについて

LenelS2 LNL-4420アクセスコントロールパネルは、2017年にHID Globalに買収されたMercury Securityが製造しています。HID Mercuryは業界のOEM提携を数多く行っているため、ビルディングオートメーションやアクセス制御業界のベンダーにとっては自然のことだったようです。今回は調査範囲に照らし、すべてのテストをLenelS2ブランドのボードで行いました。ところが、開示プロセスにおいて、この脆弱性が、Mercury製ボードを使用する20以上のベンダーに相当するすべてのOEM企業に影響を及ぼすことが判明しました。最終的には、脆弱性の開示プロセスをベンダー側で担当したCarrierと密接に連携することになりました。Carrierの開示への取り組みと協力への貢献を高く評価したいと思います。脆弱性へのパッチ適用と情報開示の過程で、Carrierのセキュリティチームと協力できたことは、素晴らしい経験でした。発見された脆弱性は、Carrierの管理下にあるソフトウェアに存在するものではなかったにもかかわらず、同社はボードのOEMパートナーの1社として、影響を受けたベンダーであるHID Mercuryとの開示プロセスを進めることに協力する責任を感じていたのです。

LNL-4420でターゲット選定を終えた後、私たちは当然ながら、できるだけ安い方法(eBayで信頼できる中古品を探すなど)でボードを入手しようとしました。数日後には、わずか数百ドルで探していた通りのボードが手に入りました。(図2)市販のマーケットプレイスでデバイスを購入したため、コントローラーの管理とアップデートに使用するOnGuardスイートなどのソフトウェアには一切アクセスしませんでした。それが支障をきたすこともなく、実際に筐体をこじ開け研究室で仕事に取り掛かりました。

図 2. HID Mercury コントローラー – OEM パネル LNL-4420

図2. HID Mercury コントローラー – OEM パネル LNL-4420


予備調査と標準的な操作

予備調査

攻撃経路を特定するための重要なステップは、ターゲットが通常の環境でどのように利用され、どのように動作するよう設計されているかを把握することです。まず、このデバイスで何ができるのか、どんな設定が公開されているのか、どのポートが開いているのか、認証はきちんと実装されているのか、などを確認したいと考えました。これらのステップは重要で、脆弱性調査を開始する際の核となるものであり、攻撃が最も影響を与える可能性のある場所に優先順位をつけることができます。

新しいデバイスで予備調査を行う際の最初のステップの1つは、どのポートが有効でリッスンしているかを確認することです。シンプルなNmapスキャン(図3)により、ターゲットに関する貴重なインテリジェンスを得ることができます。

図 3. LNL-4420 の Nmap スキャン

図3. LNL-4420 の Nmap スキャン

デフォルト設定のLNL-4420は、80(http)、443(https)、3001(不明)の3つのポートでリッスンしています。3001番ポートでは明らかにデバイスとの通信が不可能で、このポートにブラウジングしても応答がなく、netcatでポートに接続しても行き止まりでした。後でわかったことですが、これはOnGuardのソフトウェアがデバイスと通信する方法でした。httpポートにナビゲートすると、リクエストがhttpsにリダイレクトされ、典型的なユーザーログインのページが表示されます。(図4

標準的な操作

図 4. Web ブラウザーを使用してデバイスに移動すると、ログイン資格情報が求められます

図4. Webブラウザーを使ってデバイスに移動すると、ログイン情報を要求される

このデバイスはeBayで入手したため、取扱説明書やユーザー名・パスワードはありませんでした。幸いなことに、図5のように、DIPスイッチの設定に基づいたデバイスへのログイン方法が記載されているインストールガイドをインターネット上で見つけることができました。

図 5. インストール ガイドに記載されているディップ スイッチの機能

図5. インストール ガイドに記載されているDIPスイッチの機能

SW1 を「オン」に設定するだけで、

デバイスをリセットすることなく、デフォルトの認証情報である 「admin:password」が受け入れ可能となります。つまり、LNL-4420のパネルに物理的にアクセスできる人であれば、SW1を切り替えるだけで、Webインターフェースに管理者としてアクセスできるようになるのです。確かに、パネルは通常、筐体の中にあり、大抵は操作するのと同じアクセス制御の背後で物理的に保護されていますが、それでも実行可能な物理的な攻撃対象領域となっています。

DIPスイッチを適切に設定してデバイスを起動すると、管理者としてWebサーバーにログイン出来ました。そのWebサーバーにはWebインターフェースから直接設定できるオプションがいくつかあることも発見しました。(図6)

図 6. 管理 Web インターフェイスのメイン メニュー

図6. 管理Webインターフェイスのメインメニュー

この時点で、ユーザーインターフェースの各ナビゲーションタブを列挙し、どのページでユーザー入力が可能かメモを取るようにしました。ユーザー入力は、バッファーオーバーフロー、コマンドインジェクション、クロスサイトスクリプティング、任意のファイルアップロード、その他多くのネットワークやwebベースの脆弱性を誘発しようとする攻撃者にとって、格好の標的となり得ます。もし、ユーザーの入力からデバイスを誤作動させる方法を見つけることができれば、それを利用してデバイスへのエクスプロイトを試みることもできます。

いくつかのナビゲーションタブにユーザーからの入力があることを発見しました。そこには、ホーム、ネットワーク、ホスト間通信、アドバンスネットワーク、ユーザー、認証の読み込み、OSDPファイル変換、診断が含まれます。図6の注意事項の下部にあるように、特定の文字が使えないことが明記されています。これらはコマンドインジェクションのXSSSQLインジェクションによく使われる記号です。したがって、開発者は少なくとも基本的な考え方によって、一般的な入力攻撃を防御しようとしていたことがわかりました。この文字制限とWebサーバーの脆弱性を発見しようとした試みについては、第2回で改めて取り上げます。

ユーザーが入力できる設定をひとつひとつ見ていくと、この管理パネルが全貌を示しているわけではないことに気がつきました。ホスト名、IP設定、経路、証明書など、パネルのデバイス固有の設定の多くを実行することができましたが、発見した設定の中でアクセス制御機能と直接関係するものはありませんでした。例えば、バッジやカードリーダーの設定、ドアリレー、スケジュール、自動化など、アクセスコントロールパネルを予測させる機能を示す設定は見つかりませんでした。物理的なアクセス制御のセキュリティオペレーションを理解するためには、OnGuard管理ソフトウェアが不可欠だという当初の規定が補強されたわけです。OnGuardでは、管理者がLNL-4420などのコントローラーに、さまざまなカードリーダー、バッジ認証、ドア開放ポリシーなどの具体的な設定をプロビジョニングすることができます。ただし、おそらく今回の調査プロジェクトで最も重要だったのは、OnGuardのソフトウェアが制御盤のファームウェアをアップグレードできることです。問題は、OnGuardソフトウェアを入手する唯一の(合法的かつ倫理的な)方法は、マシン上でサーバーソフトウェアをプロビジョニングし、有効なライセンスをインストールできるライセンスインストーラーを経由することです。これは私たちだけでは無理ですし、もちろんeBayで購入したものには含まれていません。

それでも、標準的な操作とそれをテストするためのボードについての知識を生かし、ハードウェアの調査に取り掛かることを決め、より深いシステムの列挙と脆弱性の発見を容易にするためにルートシェルを取得することを目標にしました。


ハードウェアハッキング

すでにデバイスを開梱し、最初の偵察を行い、Web インターフェイスを検査しましたが、この時点までハードウェアに時間をかけていませんでした。調査を開始するとすぐに、十分な数の IO ポートが利用可能であることに気付きました。USB-A、SD カード スロット、20 ピン コネクタ?、4 ピン コネクタもあり、これらはすべて利用可能である可能性があります。ハードウェアのハッキング。

これは、リサーチ プロセスにおいて一時停止し、攻撃の完全な計画を立てて、目標を達成するための反復的な方法論に焦点を当て、それらを明確に文書化する絶好の機会です。私たちはこれを何もせず、すぐにはんだ付けを始めました。しかし、あなたはそれをすべきです。しかし、私たちはしませんでした。

冗談はさておき、事後分析では、ハードウェアとソフトウェアの分析に慣れていない人のために、ハイレベルなアプローチを共有したいと思います。最も単純な形では、確実なアプローチはゆっくりと動き、ターゲット ハードウェアについて可能な限り多くを特定することです。多くの場合、FCC のドキュメント、製品仕様、事前の調査、および追加の OSINT メソッドを使用して、デバイスを手にする前にこれを行うことができます。ベンダーの Web サイトからファームウェアを簡単にダウンロードできる可能性を見逃さないでください。必要がなければホイールを再作成する必要はありません。メモリやファームウェアなどのコンテンツをボードから引き出すことに焦点を当てている場合は、デバイスへのハードウェア インターフェイスが必要になります。JTAGやUARTのようなもの。最近のほとんどのデバイスでは、これらのポートに接続してファームウェアをダウンロードするだけでは機能しません。もしそうなら、ハッキング宝くじに当選したと考えてください。たとえそうであっても、暗号化されたコンテンツ、パスワードで保護されたログイン、またはブート制限のいずれかに対処する可能性があります. これを回避できれば、デバイスをエミュレートし、任意の数のツールを使用して脆弱性分析のターゲットを再作成することで、デバイスに損傷を与えるリスクなしに、研究を進めることができます。

私たちの 1 人 (Sam ではありません) は、ハードウェアのハッキングにまったく無頓着でした。このプロジェクトの私のコホートや、ハードウェアだけを見て幽霊をあきらめるチームの他のメンバーとは対照的です。したがって、ここで学んだことから手順を完全に (そしておそらく過度に詳細に) 再作成するのは楽しいかもしれないと考えました。これまでに行った手順の多くは、読者が関心を持つ可能性のあるハードウェア ターゲットに適用されるためです。以下のセクション全体で参照されるツールのクイック リファレンスを提供します。

ハードウェアハッキングのショッピングリスト

UARTによるハードウェアデバッグ

まず、UARTなどのシリアルポートを使って、コントローラーのブートプロセスにアクセスできるかどうかを確認しました。先ほど取り上げた4ピンのポートを覚えていますか?それが、この図7です。では、なぜこれがUARTのふさわしい候補になるのでしょうか。UARTはほとんどの場合、マイクロコントローラーに直接組み込まれており、送信(TX)と受信(RX)の最低2本のワイヤーだけでシリアル通信を行うことができます。このボードには他にもシリアル用の候補がありますが、4本ピンがあることを考えると、TXRX、グランド(GRD)、そしておそらく電源ピン(VCC)でしょう。確実に調べるには、ロジックアナライザーなどに接続して確認するしかありません。

図 7. 可能な UART シリアル接続ポート

図7. 可能なUARTシリアル接続ポート

UARTの候補が決まったところで、近くにあったシンプルな4線式コネクターを手に取り、ピンに差し込みました。図8のように、追跡しやすいよう4本のワイヤーを分割しました。

図 8. UART 候補に接続された 4 ピンワイヤ

図8. UART 候補に接続された 4 ピンワイヤ

デバイスを起動させたいなら、まずは電源ですね。そこで、別のペアのワイヤーを電源につなげました。DC電源を使用して、VIN(電圧入力)とGND(グランド)に接続しているボードに正確に12ボルトの電圧を供給します。図9のように、ボード上に記されているので電圧を確認することができます。電源ワイヤーの接続は図10を、LNL-4420に接続された電源の全体像は図11をご覧ください。

図 9. ボードに渡される電圧 (12V)

図9. ボードに渡される電圧 (12V)

図 10. 入力に接続された電源ワイヤ

図10. 入力に接続された電源ワイヤ

図 11. ボードに接続された UPS

図11. ボードに接続された UPS

ボードが受け取る電圧は12ボルトと決まっていたので、12ボルトに固定して供給しました。疑わしいUART4本のピンそれぞれにマルチメーターを取り付けると、ポートの電圧が3.3ボルトで、ピンの1つが接地ピンであることが容易に確認できました。

マルチメーターをお持ちでない方は、ぜひお求めください。また、必要とあれば、私たちが使っていたようなSaleaeのロジックアナライザーにピンを接続し、各ピンの機能を把握することもできます。テストクリップワイヤーハーネスを使えば、接続を簡素化し、セキュアにすることができます。

この選択肢を探ってみましょう。図12は、(おそらく)UARTに接続された4本のピンを示しています。任意の3本のワイヤー(012と呼びましょう)を選び、その出力をロジックアナライザーソフトで確認することで、TXRX、グランド、電源のどれであるかを判断することができます。任意のワイヤーを選び、ボード上の接地された金属シャーシに接続した後、Saleaeのラベル付きグランドピンの1つに接続しました。

図 12. UART に接続された Saleae Logic Analyzer

図12. UART に接続された Saleae Logic Analyzer

次にソフトウェアですが、無料で配布されているSaleaeのソフトウェアをダウンロードし、実行すると、初期設定の画面が表示されます(図13)。

図 13. Saleae の初期セットアップ

図13. Saleae の初期セットアップ

今回は、画面を見やすくするためにDigitalのみを選択し、01234本のピンを選択しました。図14は、今回設定したオプションです。通常、チャンネル(ピン0はチャンネル0)、ビットレートまたはボーレート(最も一般的なのは115200)を選択し、残りは通常、デフォルトのままにしておきます。

図 14. チャネル 0 ピン

図14. チャネル 0 ピン

10秒間のサンプリングを行いましたが、デバイスの電源投入時に送信されるデータをキャプチャするには十分でした。操作の順序としては、Saleaeのソフトウェアから「Play」または「Capture」を選択し、すぐに電源からボードに電力を供給しました。4本のピンをすべてテストした結果、次のような結論に達しました。

  • ピン0はデータを表示
  • ピン1は、スパイクが決して下がらないことから定電流であることを示しており、3.3ボルトの出力で送信(TX)だということがわかりました。
  • ピン2は、トランジェントを示し、その後何も示しませんでした。これは、「受信」モード(RX)ですが、実際には接続されていない可能性があります。
  • そして、4番目のピンであるピン3は、ボードのシャーシ金属にクリップし、グランドに接続しました。

これらの結果は、図15を見てください。

図 15. 特定された Saleae ピン配列

図15. 特定された Saleae ピン配列

注記:データを見る際は、ソフトウェアのマクロビューからズームインする必要があるでしょう。最初はブリップのように見えても、よく見ると、図15にあるようにチャンネル0のようにデータが表示されていることがあります。Dataの欄には、このようなASCIIのデータがありました。

図 16. チャネル 0 の 16 進データ

図16. チャネル 0 の 16 進データ

16進数からASCIIに変換すると、「RomBOOT」の後に改行とキャリッジリターンが続きます。この作業により、UARTによるシリアル接続が実際に行われていることが確認でき、ボードを起動すると、最初のRomBOOTシーケンスの一部がキャプチャされました。

次の論理的な手順は、UART接続でデバイスを起動させてみることです。そこで、ロジックアナライザーを取り外し、代わりにUSB-シリアルFTDIベーシックアダプターを取り付けました。これにより、UARTからノートPCPCUSBに直接接続してブートプロセスを観察することができました。図17は、その接続を示したものです。受信(RX)から送信(TX)、TXからRX、グランド(GND)からグランドを接続するピン配置としました。電圧ピンを省略したのは、すでに電源でボードに電力を供給しているからです。

図 17. USB からシリアル FTDI ベーシック アダプター

図17. USB からシリアル FTDI ベーシック アダプター

私たちは、あらゆるプロトコルの接続を確立するためのツールとして、Moba XTermを使用しています。今回は、ボーレートを115200に設定し、先ほどのロジックアナライザーのセッションを再現した新しいシリアル接続を確立しました。図18は、基本的な設定を表示したものです。

図 18. Moba XTerm セッション設定

図18. Moba XTerm セッション設定

ボードの電源を入れると、図19に示すように、セッションからの出力が確認されました。しかしすぐに、しばらくするとブートプロセスが一時停止してしまうことが判明しました(図20)が、これはUARTが無効になっているためだと考えました。これはデバイスへのシンプルなインターフェースを回避するため、私たちがこれまで説明してきた手法を使って開発者が実行しているのです。恐れることはありません、意思のあるところに道は開けるのです。

図 19. Moba XTerm の最初の RomBOOT 出力

図19. Moba XTerm の最初の RomBOOT 出力

図 20. UART 接続がデータの送信を停止した場所

図20. UART 接続がデータの送信を停止した場所

図 21. Linux コンソールへのアクセスを許可する UART ピン。

図21. Linux コンソールへのアクセスを許可する UART ピン。

UARTコンソールが無効化されただけでなく、読み込み専用になってしまいました。仮にコンソールを再び有効にできたとしても、UARTが読み込み専用ではメリットは限られます。このため、コンソールを読み込みと書き込みできるようにする方法を模索しました。そのためには、ブートローダーにアクセスして、「/bin/sh」で「init」変数を変更する必要がありました。「init」変数を変更すると、UARTインターフェースを無効にするために使用された可能性が高いすべてのスタートアップスクリプトをバイパスすることができます。これについては、この記事のUART initのところで詳しく解説しています。ここで問題が発生しました。ブートローダー(今回は「U-Boot」)は、ユーザーがブートプロセスを一時停止してU-Bootシェルにアクセスできないように設定されていました。(図22

図 22. U-Boot が無効になっているユーザー シェル

図22. U-Boot が無効になっているユーザー シェル

これは、U-Bootの環境変数 「Bootdelay」が0に設定されているためです。さらにU-Bootのドキュメントを調べてみると、値0はオートブートが有効で、インタラクティブなコマンドが完全に制限されていることがわかりました(図23)。

図 23. bootdelay の UBoot マニュアル

図 23. Bootdelay向けのU-Bootマニュアル

上の赤線枠を読むと、この変数に―1を設定すると、オートブートが無効になることに気づかれたかもしれません。この値をバイナリパッチすることが、次の戦略です。唯一の疑問は、その方法です。U-Bootを一時停止したり、対話したりする機能がないため、行き詰まりました。

JTAG を使用したハードウェアのデバッグ

そう簡単にOSに手を出そうというつもりはありません。しかし、先に述べた20ピンコネクターの話を思い出してください。経験豊富なハードウェア研究者(サムのような)には、20ピンのARM JTAG接続と非常によく似ているように見えるでしょう。それこそ、まさにJTAG接続でした。少し手間取りましたが、以下のような20ピンARM JTAGのピン配置を見つけることができました。

図 24. ARM 20 ピン JTAG コネクタのピン配列

図 24. ARM 20 ピン JTAG コネクターのピン配列

JTAGで遊ぶ時間だ!UARTJTAGは、生体構造に例えると、わかりやすくなります。CPUが脳だとしたら、JTAGは思考の制御です。オンボードのUART接続により、ユーザーはデバイスのコンソールと対話することができますが、JTAGにより、ユーザーはメモリの読み込みと書き込みや実行の完全制御といったデバイスの内部動作と対話することができます。Seggerj-linkという素晴らしいJTAGデバッガーを製造しています。J-LinkCPUとの対話を可能にし、ブレークポイントの発行、メモリやレジスターへのアクセス、基本的なスクリプトの実行などの機能を効果的に提供します。ここではPro版を使用しました。

24に示すように、5ボルトのピンと最下列のグランドピンをマルチメーターで確認することで残りのピンの向きを把握しました。ボードの下からj-linkで接続することをイメージして、目視でピンを並べることができました。右側のGNDピンの1つに1本のグランドワイヤーを付け、Seggerwebサイトで定義されているように、VTref(ワイヤーの色:茶)、nTRST(赤)、TDI(オレンジ)、TMS(黄)、TCK(緑)、RTCK(青)、TDO(紫)、RESET(ベージュ)のワイヤーを j-linkにつなぎます。ピン配置画像の「ノッチ」は、j-linkのデバイスに「Target」と表示されているところで、どの向きに使用すればいいかもわかっていました。図26に完成したレインボー配線のピン配置を示します。

図 25.JTAG から j リンクへの配線

図25. JTAGからj-linkへの配線

jlinkソフトウェアは、Seggerからダウンロードすることができます。UARTセッションで「Autoboot」が画面に表示されると同時に、WindowsPowershellを使って必要なコマンドを実行しました。図26のショートカットを使うと、プログラムでブートプロセスを停止させることができました。

図 26. JLink

図26. JLink の「ブレークポイント」スクリプト

break.jlink」は、実は、非常に優れたスクリプトで、本日、公開して共有することにしました。図26で参照したデバイスCPUat91sam9g45」は、以下の図27に示すようにATMELのチップから取り出したものです。

図 27. ATMEL ARM チップ ATSAM9G45

27. ATMEL ARM チップ ATSAM9G45

このスクリプトにより、j-linkを使用したU-Bootより先に一時停止することができました。図28のスクリーンショットは、停止した状態のデバイスのブートプロセスを示しています。

図 28. UBoot の前に一時停止する JLink

図28. UBoot の前に一時停止する JLink

ブートプロセスを一時停止することができるものの、「Bootdelay」パラメーターによってターミナルとの対話が不可能になるという課題が残っていることを思い出してください。

U-Boot Bootdelayの変更

上記の図22から、U-Bootのコードは0x20000のメモリから実行可能なメモリ空間である0x73f00000の場所にコピーされることがわかります。このコピーの直後に、U-Bootが実行されたことを確認しました。論理的には、図22にあるように、「Hit Keys to Stop Autoboot」という文字列の位置にJTAGで戦略的なブレークポイントを置く必要があることを意味します。

しかし、この画像の大きさを考えると、どのアドレスでブレークすればいいのか迷いました。次に、JLinkの「SaveBin」コマンドを使用して、U-Bootのコードをメモリからダンプしました(図29)。

図 29. 実行の停止と U-boot コードのダンプ

図29. 実行の停止と U-bootのコードのダンプ

ようやく、機能的な「バイナリ」が手に入りました。これは、生のメモリダンプでありながら、実際のU-Boot実行ファイルを含んでいます。次にバイナリ解析に取り掛かります。

逆アセンブルとデバッグ

このバイナリを、事実上の逆アセンブルツールであるIDA Proに読み込ませました。PEELFのような多くの既知のバイナリでは、読み込み中にIDAが多くのコード解析と定義を行います。今回は、生のメモリダンプだったので、簡単なクリーンアップをしなければなりませんでした。すべての優れたリバーサーと同様に、最初にstringsコマンドを実行し(図30)、U-Bootprint文の位置を特定しました。

図 30. 「Hit keys to stop autoboot」の文字列検索

図30. 「Hit keys to stop autoboot」の文字列検索」

IDAや他の逆アセンブルツールのホットキーを知ることは、迅速なリバーシングや解析に有効です。文字列を実行するためのデフォルトのホットキーはShift+F12です。読み込み専用メモリの文字列アドレスを見つけた後(図31)、バイナリサーチを行い、メモリ内の文字列の真のアドレスを見つけました(図32)。

Figure 31. 文字列の ROM アドレス

図31. 文字列の ROM アドレス」

図 32. 即時値の二分探索

図32. 即時値の二分探索”

アドレスのバイナリサーチを行う必要があったのは、この時点では必ずしもすべてのコード関数がIDAで正しく定義されていなかったためです。その結果は図34の通りで、未定義のコードのバイト列にたどりつきました(図34)。私たちはARMの命令コードをネイティブで話すわけではないので、デフォルトのホットキー「c」を使ってコンテンツをコードとしてマークし、「p」を使ってコードをプロシージャまたは関数としてマークして、コードとグラフの両方の表示をより読みやすくしました(図35)。文字列を見つけたときは、ホットキー「o」を使ってIDAに文字列のオフセットであることを伝えました。

図 33. 二分探索の検索結果

図33. 二分探索の検索結果」

Figure 34. 二分探索結果の ROM アドレス

図34. 二分探索結果の ROM アドレス」

図 35. プロシージャとしてマークした後のコード ビュー

図35. プロシージャとしてマークした後のコード ビュー”

これで、コードがずっと読みやすくなったので、先に進めます。これまで見たように、デバイスはU-bootコードを0x73000000のアドレス空間に読み込みましたが、実行が転送される前に再配置されました。その証拠として、アドレス範囲0x73000000を使用している間、どのブレークポイントもヒットしませんでした。ブレークしたい実際のアドレスを見つけるには、U-bootコードの「内部」でCPUを停止させる必要がありました。図29J-Linkブレークポイントコマンドを思い出してください。

J-Linkに自動的に接続し、デバイスが認識されると同時にCommanderScriptを実行し、ブレークポイントをトリガーします。この時点で、コンソールに「U-boot 2013.07…」の文字列が表示された後、「Hit keys to stop autoboot: 0」文字列が表示される前にCPUが停止しました。

U-Bootの実行に入ったら、U-Bootのメモリがどこにリマップされているのかを探さなければなりませんでした。このため、新たにリマップされたメモリ範囲から、先に取得した0x73000000アドレスからのメモリダンプと整合するアドレスを特定する必要があります。

現在の命令で便利なJ-linkの「mem」コマンドを活用して、プログラムカウンター($PC)の位置から0x10バイトのメモリをプリントアウトしました。コピーされた0x10バイトは、逆アセンブラーでマッピングできる十分大きな一意のバイト列を見つけるという目標に基づいて、任意に選択されたものです。IDAでは、「バイト列の検索」(Alt+b)オプションを使って、これらの16バイトの命令を検索することができました。一般に、この検索に提供されるバイトが多ければ多いほど、一意のマッチングができる確率が高くなります。

検索努力の結果、元のU-Bootイメージのどこに位置していたかというコンテキストを得ることで、現在のプログラムカウンター($PC)のアドレスを取得し、U-Bootダンプで見つかった位置から差し引くことができました。これにより、U-Bootが現在実行されている位置からのオフセットが得られ、物理デバイスに一致するバイナリをリマップすることができました。IDAのもうひとつの重要な機能は、指定されたアドレスに基づいてイメージ全体をリベースする機能です。これはASLRのように、実行時にイメージのベースアドレスを変更する場合に便利です。「編集セグメントリベースプログラム」を選択することで、算出したオフセットを新しいイメージベースとして供給しました。

最後に、J-Linkを利用して、「Hit keys to stop autoboot: 0」という文字列をプリントアウトした直後に、ブレークポイントをセットすることができました。文字列をプリントして間もなく、図36にあるように、「Bootdelay」の値はレジスターR0によってstrtol()に渡されました。システムのデフォルト値はリトルエンディアン「0x3000」で、ASCIIの「0」を表す16進数値です。これはブート遅延がないことから予想されていたことです(それゆえにこの演習全体の要点なのです!)。最後のステップでは、2バイトの書き込みコマンド「w2」で、この値を「-1」、つまり0x312dに置き換えました。(36)

図 36. ブレークポイントの設定と「bootdelay」の「-1」への変更

図36. ブレークポイントを設定し、’bootdelay’ を ‘-1’ に変更

この時点で、無効になっていたU-Bootシェルが再び有効になり、実行を続けると自動的にU-Bootシェルにドロップされました。図37で示されたU-Bootの「help」コマンドは、これを示しています。

図 37. 機能している UBoot シェルにドロップ

図37. 機能している U-Boot シェルにドロップ

U-Bootシェルから、今度はデバイスのブートプロセスを変更する必要がありました。このレベルでは、「init」やPID 1としてどのバイナリを使用するかなど、Linuxカーネルの起動方法に関するパラメーターを変更することができました。他のシステムソフトウェアがUARTコンソールを無効にする原因になっているという懸念もあり、図38に示すようにinit変数を「/bin/sh」に変更し、初期のスタートアップスクリプトを一時的にオーバーライドしました。

図 38. 「init=/bin/sh」を bootargs 変数に追加

図38. bootargs変数に「init=/bin/sh」を追加

新しいinit変数を設定すると、システムが設定したデフォルトのinitプロセスは(一時的に)上書きされ、指定された「sh」バイナリに直接実行がドロップされます。必要なのは、U-Bootからブートを呼び出し、上書きされたinitに取得を任せることだけでした。(図39

図 39. UBoot から Boot を呼び出し、Linux でルート シェルを取得する

図39. U-Bootからブートを呼び出し、Linuxのルートシェルを取得

ルートシェルのビデオデモ

話が一巡したところで、この短いデモビデオを見ると、ルートシェルにつながるこれらの取り組みの結果を確認できます。

さて、この検証騒ぎは少し制御不能になりましたが、私たちはスタート地点に戻ってきました。

信じられないような話ですが、ようやくファームウェアの脆弱性解析に着手できるようになったのです。孤独なハッカーの人生とは、そんなものです。続きが気になるところで申し訳ありませんが、技術ブログシリーズの第1回はここまでとさせていただきます。次回は1週間後を予定しています。ゼロデイ脆弱性の探し方を詳しく説明します。脆弱性発見のプロセスを深く掘り下げ、いくつかの欠陥のある開発実装がいかにして重大なセキュリティ問題を引き起こしたかを紹介します。ご期待ください!

本記事およびここに含まれる情報は、啓蒙目的およびTrellixの顧客の利便性のみを目的としてコンピュータ セキュリティの研究について説明しています。Trellixは、脆弱性合理的開示ポリシーに基づいて調査を実施しています。記載されている活動の一部または全部を再現する試みについては、ユーザーの責任において行われるものとし、Trellixおよびその関連会社はいかなる責任も負わないものとします。

Trellixは、米国およびその他の国におけるMusarubra US LLCまたはその関連会社の商標または登録商標です。その他の名称やブランドは、該当各社の商標または登録商標です。

※本ページの内容は2022年8月11日(US時間)更新の以下のTrellix Storiesの内容です。
原文:A Door Isn’t a Door When It’s Ajar – Part 1
著者:Sam QuinnSteve Povolny