リニューアル後のブログでは初めましてになります。しゅーとです。
今回は、EOL(End-of-Life、サポート終了)になった機器を調査したら脆弱性を見つけてしまった話です。どんなものを見つけたのか、脆弱性の原理を説明します。
なお今回見つかった脆弱性はメーカーに報告しており、2021年5月にセキュリティアドバイザリが公開されました。(CVE-2021-1400, CVE-2021-1401)
報告した製品はEOLを迎えているので修正リリースはありませんが、現役製品にも刺さったようで、サポート対象製品では修正リリースが公開されています。サポート対象の製品を利用している方はアップデートしましょう。過去の私のようにEOLに気づかず運用している方は利用を停止してください。(脆弱性情報は記事のうしろにあります)
発見までの経緯
私の自宅では長い間「Cisco WAP131」というアクセスポイントが我が家のトラヒックを処理していました。これはCiscoが「Cisco Small Businessシリーズ」と謳っている中小企業向けアクセスポイント製品なのですが、去年のはじめにリモートワークに伴う自宅整備を進めるために見直したところ、既にEOLを迎えていました。気づいた私は慌てて新しいものにリプレースをしたのですが、こうして余ったAPが一台。そしてIoTペネトレーションテストをサービスしている人間が一人。
せっかくなので、研究対象として調査することにしました。
ファームウェア調査
まず初めに調べるのは、メーカーサポートサイトです。幸いサポートサイトにいくと、ファームウェアのアップデートファイルが配布されているようなので、最新版をダウンロードしました。
アップデートファイルはtar形式で配布されており、ダウンロードして展開すると、4つのファイルが存在しました。その中で一番サイズが大きかったのはrootfs.bin
というファイルです。未知のファイルの形式を調査するには、定番のfileコマンドのほか、binwalkというソフトウェアが便利です。
binwalkを実行してみると、以下の結果が得られました。
$ binwalk rootfs.bin DECIMAL HEXADECIMAL DESCRIPTION -------------------------------------------------------- 0 0x0 TRX firmware header, little end(..snip..) 28 0x1C LZMA compressed data, properties: 0x5A, dic(..snip..) 1835008 0x1C0000 JFFS2 filesystem, little endian --------
わかりやすいもので助かりました。0x1Cから始まるチャンクはLinuxカーネルのようで、0x1C0000はJFFS2形式のファイルシステムのようです。今回はルートファイルシステムを知りたいので、中身を抽出することにします。binwalkにも展開コマンドがありますが、ここでは手動で展開することにしましょう。
まずはddでJFFS2にあたるチャンクを切り出し、JFFS2を展開できるソフト「jefferson」で展開します。
$ dd if=rootfs.bin of=jffs.bin bs=1 skip=1835008 status=progress 30692666 bytes (31 MB, 29 MiB) copied, 57 s, 538 kB/s 31191040+0 records in 31191040+0 records out 31191040 bytes (31 MB, 30 MiB) copied, 57.9325 s, 538 kB/s $ file jffs.bin jffs.bin: Linux jffs2 filesystem data little endian
fileコマンドの結果からJFFS2ファイルシステムが取り出せたことがわかります。次はjefferson。
user@research:~/wap131_work$ jefferson -d jffs-work jffs.bin dumping fs #1 to /home/user/wap131_work/jffs-work/fs_1 Endianness: Little Jffs2_raw_inode count: 34392 Jffs2_raw_dirent count: 1785 Jffs2_raw_xattr count: 0 Jffs2_raw_xref count: 0 Jffs2_raw_summary count: 0 writing S_ISDIR bin writing S_ISDIR dev writing S_ISDIR etc writing S_ISDIR home writing S_ISDIR lib (..snip..)
展開できたようです。
Linuxファイルシステムです。ここまでスムーズに展開できましたが、実際の診断業務のあれこれと比べると、今回はかなり楽な部類です。
脆弱性調査
ルートファイルシステムを抽出でき、Linuxであることがわかったのであとは気合です。機器でどのソフトウェアが動いているのか、ブートシーケンスのはじめのほうであるrcスクリプトから追っていき、それらしいサービスのバイナリを探していきます。今回は対象機器にWeb管理画面があるのでそこを探してみると、/home/httpd
がwebrootであることがわかりました。
webrootにはCGIプログラムがいくつかあり、検証用に稼働させている対象機器のWeb管理画面のパスと照らし合わせると、どのCGIがどんな機能を持っているのか、おぼろげながら浮かんできます。CGIはバイナリ形式だったので、リバースエンジニアリングツールのGhidraを使ったりして探していきました。
で、結局2つの脆弱性を発見しました。OSコマンドインジェクションとアクセス制限不備の脆弱性です。OSコマンドインジェクションは悪用のために管理者権限ユーザが必要ですが、同時に見つけたアクセス制限不備の脆弱性を悪用すると一般ユーザから管理者ユーザに昇格できる可能性があるので、CVSSでは測れない深刻さが漂います・・・。
それぞれの脆弱性を紹介します。
アクセス制限不備 (CVE-2021-1400)
CVSSスコア: 8.8
本脆弱性は機器ファイルシステム上のシンボリックリンクの不適切な配置と公開ディレクトリの権限不備の問題に起因して生じるものです。
先ほどwebrootを見つけましたが、本来あるべきではない、複数の内部設定ファイルが保存されたディレクトリへのシンボリックリンクファイルが存在していました。なお解析の結果、機器管理画面のうちログイン用APIおよび画像などのリソースパス以外は、認証されたユーザ以外はアクセスできないように制限されていることを確認しています。このことから本脆弱性は、少なくとも一般ユーザのアクセス権限が必要です。
対象機器へ、ユーザ認証後に当該パスにアクセスすると、内部設定ファイル一覧が表示されました。存在する設定ファイルについても一部を除いてほとんどのものが一般ユーザ権限で閲覧可能でした。
これらの設定ファイルを確認すると、管理者ユーザのパスワードハッシュ、および管理者ユーザを含む各ユーザのログインセッション情報が存在しました。パスワードハッシュについては著名なパスワードクラックツールにて利用可能なハッシュ形式であることを確認しています。
この脆弱性を用いることで管理者ユーザのなりすましが可能になるため、仮に攻撃者が侵入当初は一般ユーザ権限のみを窃取していたとしても、次に説明するコマンドインジェクションの脆弱性が利用可能となってしまいます。
シンボリックリンク1つでここまで悪用できると怖いものです。開発時に不要なファイルは置かない、必要な場合でも最小限に留めることを原則にしていただけるといいかと思います。
OSコマンドインジェクション (CVE-2021-1401)
CVSSスコア: 5.5
本脆弱性は機器Webアプリケーションのバリデーション不備の問題に起因して生じるものです。
webrootに存在するCGIファイルをGhidraで見ていたところ、特定のAPIにおいて一部の入力値を、シェルを実行する言語機能である「system()」の引数として利用している処理が存在しました。
一般的にユーザからの入力値をsystem()の引数に利用するのはセキュリティ上の問題が発生する可能性が高く、IPAでもこのような処理は望ましくない実装だとして「安全なウェブサイトの作り方」に概要と対策方法を記載しています。
安全なウェブサイトの作り方 - 1.2 OSコマンド・インジェクション
本アプリケーションにおいてもユーザ入力値のバリデーション不備により、特定のリクエストをWebサーバに送信することでOSコマンドインジェクションが可能でした。さらにWebアプリケーションはroot権限で実行されていることから、OSコマンドもroot権限で実行されます。
OSコマンドインジェクションの脆弱性を有するAPIは管理者ユーザにのみアクセス可能ですが、先のアクセス制限不備の脆弱性を悪用することで、一般ユーザ権限でも管理者ユーザ権限を窃取して実行が可能になります。
ネットワーク機器ではOSの設定変更を伴う関係で、処理中にOSコマンドを使いたくなるのもわかります。しかし脆弱性の温床になりがちなので可能な限り使わないようにしましょう。どうしても使う場合は必ず値の検査を。
公表までの経緯
脆弱性を2つ見つけてしまいましたが、対象機器は既に発見当時、EOLから半年経過していました。しかし、引き続き利用しているユーザへの注意喚起目的と、EOLを迎えていないが同様の脆弱性が存在する可能性のある同シリーズの別製品の影響を鑑みて、脆弱性報告を決意しました。結果的にEOLを迎えていない別製品にも同様の脆弱性が含まれていることがセキュリティアドバイザリの内容から判明したため、報告して良かったです。皆さんもEOLな機器で脆弱性を発見したときは、EOLでもIPAに報告するようにしましょう!
本問題は、情報セキュリティ早期警戒パートナーシップに基づき、ラックからIPAに報告し、JPCERT/CCにより開発者との調整が行われました。EOLを迎えた製品の報告にも迅速な対応を行い、脆弱性対象の機器を洗い出し修正リリースを公開したCisco社に感謝します。
脆弱性情報
こぼれ話
調査機器がLinuxで動いていると、解析難度が低くなるので大変ありがたいです。
ところで、先日METIが公開したセキュリティ検証の手引きはみなさん読まれましたか?
この手引きはIoT機器に対してどういうアプローチでセキュリティ診断を行えばいいのか、ある程度網羅的に示した画期的な文書です。今回私が発見した脆弱性も、手引きの別冊1記載の手法を参考に調査することで、恐らく見つけることができます。IoTセキュリティ診断に興味がある方はぜひ秋葉原でジャンクルータを買ってきて解析しましょう!
「・・・なんだ、手引き簡単やん」と思った方は安心してください。
実際の業務では、この手引きでは必ずしも適用できない部分が多々あります。この手引きはWebカメラやネットワークルータなど、Linuxが搭載されているようなある程度リッチな製品を対象にしています。しかし私の所属しているデジタルペンテストサービス部では、Linux製品に限らない車載ECUや医療機器などの組み込み系システムも診断サービス提供範囲なので、機器にリアルタイムOSが載っているパターンもあります。そうなってくるとまずLinuxではないので、チップからファームウェアを抜き出したとしてもbinwalkで簡単に展開というわけにもいきません。ダンプデータやメーカ独自に暗号化・圧縮されたファームウェアアップデータを俯瞰してデータ構造を察して抽出したりする必要が出てきます。リアルタイムOSの場合はOSのコードを理解して、ファームウェア全体からOS部分をより分けてユーザコード部分を見つけ出す胆力が必要になります。ほかにも・・・いろいろ・・・・
・・・最後は嘆きみたいになってしまいましたが、リバエンの果てに脆弱性を見つけられたときはとても気持ちいいです。リバエンといえばマルウェア解析という意見もありますが、IoTぺネトレだって負けていません!解析が好きな人はぜひIoTセキュリティに飛び込んでください!
おわり。