はじめに
最近、HP DVLabsがBelkin N300 Dual-Band Wi-Fi Range Extender (F9K1111)に少なくとも10件の脆弱性を発見した。レスポンス 、Belkinはファームウェア・バージョン1.04.10をリリースした。これはF9K1111のために発行された最初のアップデートであり、脆弱性の公開トリガーがなかったため、我々はより深く調べることが興味深いだろうと考えた。
アップデートの解凍
分析を始めるにあたり、ベンダーからファームウェア・アップデートをダウンロードした。binwalkというファームウェアツールを使ってアップデートを解凍した:
binwalk -Me F9K1111_WW_1.04.10_upg.bin
その結果、以下のように、デバイスのルートを表すSquashFSファイルシステムが標準的な形で取り出された。
さて、バインディフを実行するためには、パッチを当てる前の状態のファイルを得るために、ハードウェアと少しやりとりする必要がある。
ベース・ファームウェアの入手
ベース・ファームウェアを解析するためには、物理的なデバイスからデータをダンプする 方法が必要である。そのためには、まずデバイスを筐体から取り出さなければならない。
赤と青で強調表示されているのは、それぞれファームウェア、SPIフラッシュチップ、UARTインターフェイスを検索するための可能な手段である。UARTではある程度の動作が確認できましたが、SPIフラッシュチップ上のベースイメージを解析することで進めます。今回使用するチップMX25L1606eのピンアウトは、Macronix社から入手可能です。
このシートを手に取り、チップを取り外したら、GoodFETを上記の一般的な8ピンのピン配置に合わせて配線する準備ができた。
7番ピンと8番ピンをブリッジした後、以下の方法ですべてが正しく接続されていることを確認します。
python goodfet.spiflash info
次に、goodfet.spiflash dumpを実行して、チップの内容を取得することができる。
python goodfet.spiflash dump s
最後に、出来上がったファイルの文字列を調べて、ダンプが正当なものであることを確認する (つまり、少なくとも可読性のある文字列が含まれている)。
出来上がったバイナリファイルは、以前と同じようにbinwalkでうまく解凍できる。
アップデートの差分
解凍した両方のファイルシステムをWindowsに移し、WinMergeにドロップしてみると、あまり変化がないことがわかる。
compiler_data、version、FUNCTION_SCRIPTファイルには、興味深い変更は含まれていません (フィンガープリントに有用なデータは別として)。util_system.aspへの変更もあまり興味深いものではない。ということで、私たちは、Belkinのwebsに対する変更、GoAhead Webserverを見ていきます。
ウェブの分析
HPのZero Day イニシアチブでは、影響を受ける関数名または入力と思われる脆弱性に名前を付けている。それらは以下の通り:
- formWpsStart pinCode リモートコード実行の脆弱性
- formWlanSetupWPS wps_enrolee_pin リモートコード実行の脆弱性
- formWlanMP リモートコード実行の脆弱性
- formBSSetSitesurvey リモート・コード実行の脆弱性
- formHwSet リモート・コード実行の脆弱性
- formConnectionSetting リモート・コード実行の脆弱性
- formAccept リモート・コード実行の脆弱性
- formiNICWpsStart リモート・コード実行の脆弱性
- formUSBStorage リモートコード実行の脆弱性
そこで、パッチを当てたバージョンのwebsをIDAにロードした後、関数のリストからformHwSetを探したが、何も見つからなかった。実際、これらの関数の多くは見つからなかった。Bindiffを引っ張り出してみると、アップデート中に7つの関数が削除されていることがわかる:
これらは ZDI 会報のデータとよく一致している。実際、formWlanSetupWPSとformBSSetSitesurveyを除いて、ZDIの勧告に記載されている関数はすべて削除されている。では、削除された関数を少し見てみよう。
フォームUsbストレージ
最初に考える関数はformUsbStorageである。この関数をざっと読んでみると、何が問題なのかは一目瞭然です。GoAheadのウェブAPI関数websGetVarを介してアクセスされるPOST変数sub_dirは、systemへの呼び出しで使用され、コマンド・インジェクションを可能にしている。
このコードは、次のような方法で発動される:
wget --post-data="sub_dir=vectra;reboot" http://belkin.range/goform/formUSBStorage
フォームWlanMP
同様のエラーは actionformWlanMP フォームにもあります。websGetVar のコールをトレースすると、いくつかの可能性が見えてきます。
forwaredに従うと、これらのいくつかの可能性はすべて、システムコールへのインジェクションの手段として機能することがわかる。
このコードは、次のような方法で発動される:
wget --post-data="ateFunc=;reboot;" http://belkin.range/goform/formWlanMP
フォームHwSet
ここではさらにコマンドインジェクションがあり、今回は変数[sic]アンテナを使用している。
このコードは、次のような方法で発動される:
wget --post-data="Anntena=;reboot;" http://belkin.range/goform/formHwSet
フォーム接続設定
ここでは、formConnectionSetting関数のtimeOutパラメーターにコマンド・インジェクションを設定している。
このコードは、次のような方法で発動される:
wget --post-data="timeOut=1;reboot;" http://belkin.range/goform/formConnectionSetting
フォームBSSetSurvey
この時点で、私たちは削除された関数の馬を死ぬほど叩いた。Belkinが削除を見送った関数のうち、より重要なもの、formBSSetSitesurveyを見てみよう。以下がその概要である:
恐怖の反動に襲われた後、ズームインしてみると、大きな変更点として、Belkinがstrcat_escapeという関数を追加したことがわかる。
This strcat_escape function takes 3 buffers - dst, src, and tokens. The function uses nested loops to search the src string for existence of any of the tokens to be escaped, if found they are escaped before being copied into dst. In the pictured case token_of_none_quotation is passed as tokens which is defined as"\\\"'$()<>` #&*
ウェブのバイナリからこの関数をCで再実装し、期待される出力を見ることができた:
この(おそらく正しく)エスケープされた文字列は、前と同じようにsprintfを介してシステムに渡される。
このパッチの効果は、いくつかの要因に左右される:
- strcat_escape関数は完全に意図したとおりに動作する。
- strcat_escapeが意図せずバッファオーバーフローを引き起こすことはない ;-)
- strcat_escapeは、システムで終了するすべてのユーザー入力に使用されます。
- 私たちは、これらの箇条書きのいくつかについてベルキンと連絡を取っています。
結論
セキュリティの成熟度が組込み機器コードの問題であることは、すでに誰もが認識している。ここでは、2014年に発売されたデバイスでさえも、問題が残っていることがわかる。