ここから本文です

Androidマルウェアによるシステム改ざんを検知する技術

@IT 8月3日(水)6時10分配信

●ますます巧妙化するAndroidマルウェア

 Androidセキュリティの最新動向を紹介する本連載。前回はプライバシー情報などを取得しようとするアプリの挙動を監視する技術について解説した。今回のテーマは「Androidマルウェアによる“システム改ざん”の検知技術」だ。Androidスマートフォンのユーザーであるあなたは、自分の端末がマルウェアに感染していないと言い切ることができるだろうか?

【その他の画像】ARM社開発者向けガイドにおけるセキュアブート

 近年、Androidを狙うマルウェアはますます巧妙化してきており、AndroidのシステムやOSの脆弱(ぜいじゃく)性を使用してルート権限を奪取し、ユーザーの知らない間にシステムを改ざんするものも登場している。そのため、多くのユーザーは、自分がマルウェアに感染したことに気付かない。例えば、2015年のチェック・ポイントの報告によれば、表向きはゲームアプリだが、裏ではルート権限を奪取してシステム領域に不正なプログラムをインストールするマルウェアが観測されている。また、同様のマルウェアは他にも幾つか報告されている。

 こうしたマルウェアは、主にサードパーティーのアプリストアやWebからのダウンロードなど、「Google Play」以外で配布される非公式アプリにおいて多く発見される。広告表示が目的のマルウェアなどであれば、不審な広告が目に見えて増えるためユーザーがマルウェア感染に気付きやすいが、ユーザーに隠れてシステムを改ざんし、ひそかに通信を行うようなマルウェアへの感染に気付くのは難しい。

 このようなマルウェアへの有効な対策技術としては、「Androidのブート時(電源を入れたとき)に、システムが正常な状態と比べて改ざんされていないことをチェックする」という方法がある。今回は、このAndroidブート環境におけるセキュリティ技術が、マルウェアによるシステム改ざんをどのように検出するのか解説しよう。

●Androidのアーキテクチャとマルウェアの動作

 図1に示す通り、Android OSは幾つかのレイヤーから成り立っている。一番下には「OSカーネル(Linuxカーネル)」があり、その上にGoogleが開発したAndroidシステムである「ライブラリ層」「Androidランタイム層」「アプリケーションフレームワーク層」、そして最上位に「アプリケーション層」が存在する。

 権限としては、一番下のLinuxカーネルが最も強い権限である「カーネルモード」で動作しており、Linuxカーネルより上のレイヤーは、ユーザーモードで動作する。その中でも「ライブラリ層」から「アプリケーションフレームワーク層」までのAndroidシステム層は、ユーザーモードの中で最も強力な権限であるroot権限やsystem権限で動作し、最上位のアプリケーション層は、アプリごとに与えられるUID(User ID)を基にしたさまざまな制限下で動作している。

 このAndroidアーキテクチャは、ROM上の4種類のイメージファイル(bootloader.img、boot.img、system.img、userdata.img)から構成されており、これらが以下の順番で起動していくことで、Androidが立ち上がる。


1. ブートローダがRAMにロードされ実行される(bootloader.img)
2. ブートローダがOSカーネルをRAMにロードし、OSカーネルを実行する(boot.img)※端末ごとに設定された特殊操作により、通常のOSカーネルを起動せずに開発者向けの「fastbootモード」に移行することもできる
3. OSカーネルのFileSystem/systemに、Androidシステム(system.img)がマウントされる
4. OSカーネルのFileSystem/dataに、ユーザーデータなど(userdata.img)がマウントされる

 「/system」にマウントされるのがAndroidシステムで、システムの動作に必要なバイナリやデータが格納されている。Androidの実行中、これらの情報は基本的に読込専用に設定されており、システムアップデートなどを除けば更新されることはあまりない。一方、「/data」はさまざまな設定情報やユーザーがインストールしたアプリ、ユーザーデータなどが格納される場所であり、Androidを使い続ける限り、頻繁に更新されていく。

 このアーキテクチャに対して、冒頭で説明したシステム改ざんを行うマルウェアは、典型的には以下のような手順で不正行為を行う。


1. ユーザーがマルウェアのアプリケーションを実行する
2. アプリケーションがLinuxカーネルの脆弱(ぜいじゃく)性を使用してカーネル権限でRAMを操作し、自身の権限をroot権限へと昇格させる
3. /systemの内容を改ざんし、不正プログラムを配置する

 このときよく利用される不正プログラムが「su」である。これに必要な設定を施して「/system/bin」に配置しておくことにより、マルウェアはいつでもroot権限に昇格できるようになる(注)。

*注
Android 5.0より前のバージョンの場合。Android 5.0以降はセキュリティが強化されたため、もう少し“工夫”が必要になっているが、システム改ざんを行うマルウェアは依然存在している。


 さて、それでは以下で、ROM上のイメージファイルの改ざんを検出する技術の1つである「セキュアブート」について解説しよう。

●セキュアブート

 「セキュアブート」とは、ROM上のソフトウェアが端末ベンダー(もしくは利用者)の意図したソフトウェアと同一であるかを確認するために、ソフトウェアを実行する前に、暗号技術を使ってソフトウェアの改ざんを検出する技術のことである。

 より具体的に説明すると、セキュアブートでは、改ざんすることが物理的に難しいハードウェアなどの「信頼の基点(Root of Trust)」を開始点として、次に起動するソフトウェアを“正しさが検証されたソフトウェア”に限定することにより、「信頼の連鎖(Chain of Trust)」を形成していく。そして、システム全体を端末ベンダー(もしくは利用者)が意図した状態で起動させる。Android端末が搭載するプロセッサを設計しているARMは、セキュアブートの構成や運用の指針を開発者向けガイドに示しており、次のような準備と起動の手順を推奨している(図3、関連リンク)。

・製造時

1. 端末ベンダーは、準備として公開鍵ペア(公開鍵PuKと秘密鍵PrK)を生成する
2. 端末ベンダーは、RSA-PSSなどの公開鍵暗号を使った署名アルゴリズムを用いて、開発したソフトウェアの署名を秘密鍵PrKで生成する
3. 端末ベンダーは、端末の製造時にROMにソフトウェアとその署名の両方を書き込むとともに、公開鍵PuKをプロセッサ内に確保したOTP(One Time Programmable)メモリに書き込む。OTPメモリは一度しか書き込むことができず、改ざんが困難であるため、これを端末における信頼の基点(Root of Trust)とする

・端末起動時

1. Android端末の起動プログラムは、SoC(System on a Chip)内蔵メモリ上で署名検証アルゴリズムを使い、ソフトウェアの署名をOTPメモリの公開鍵PuKで検証する
2. この署名が正当であれば、改ざんされていないと見なしてソフトウェアを実行する

 セキュアブートは、端末ベンダーの意図したシステムを起動するためのものであるが、ハードウェアのサポートが必要であるため、実質的にはQualcommやSamsungなどのプロセッサベンダーがそれぞれのセキュアブート仕様を設計している。詳細な仕様は公開されていないが、各ベンダーのカタログスペックにはチップのセキュリティ機能としてセキュアブートの記載がある。

 このセキュアブートを、Android起動時にuserdata.imgを除く3つのイメージ(bootloader.img、boot.img、system.img)に適用することで、システム領域が改ざんされていないことを検出できる(図4)。userdata.imgは先に説明した通りユーザーによって追加されたデータなどが格納される場所であり、頻繁に更新されることや、システムに比べて重要性の低いデータが格納されることなどの理由から、セキュアブートの対象外とするのが一般的である。

 ところが、前述のセキュアブート対象とすべき3つのイメージのうち、system.imgについてはほとんどの端末でセキュアブートされていないのが実情である。これには2つの理由がある。1つ目は、イメージサイズが大きい(boot.imgの約100倍、数ギガバイトになる場合もある)ために、セキュアブート方式で検証しようとすると、メモリリソースが大きく消費され、起動が著しく遅くなってしまうこと。そして2つ目が、小規模更新パッチであるOTA(Over The Air)アップデートがファイルレベルで行われるために、更新後のsystem.imgがビットレベルでの同一性を保持できず(ファイルの内容は同じでもメタデータなどが異なってしまう場合がある)、完全な同一性が求められるセキュアブートが実施できなくなってしまうことである。

●dm_verityによるシステム領域の保護

 このsystem.imgの検証に伴う2つの問題を解決するため、Android 6.0から必須機能として導入された技術が、「dm_verity」である(関連リンク)。dm_verityでは、system.imgを4キロバイト単位のブロックに分割して、各ブロックのハッシュ値をツリー形式で構成した「Hash Tree」を事前に計算しておく(図5)。そしてこのHash Treeから作成したサイズの小さいメタデータの一部(dm_verity_table)だけをセキュアブートの検証対象とすることで、system.img全体を検証する場合に比べて、起動時間を現実的な時間内に短縮する。

 また、Hash TreeそのものはAndroid起動時には検証されないが、Android実行中にファイルシステムへの読み込みが発生した際には、Hash Treeを動的に計算して完全性をチェックする。これにより、改ざんを検出できるようになっている。

 さらにAndroid 6.0では、ブロックレベルの完全性を検証するdm_verityの設計に合わせて、OTA更新パッチも、ビットレベルの同一性を確保するために、ファイルレベルからブロックレベルに変更されている。dm_verityのフローを整理すると、以下のようになる。

・端末製造時

1. 端末ベンダーは、準備として公開鍵ペア(公開鍵PuKと秘密鍵PrK)を生成する
2. 端末ベンダーは、system.imgを4キロバイトごとのブロックに分割し、ハッシュ関数(SHA-256)を使って図5のようなHash Treeを構成する
3. 端末ベンダーは、Hash Treeを基にdm_verity_tableを作成する(図7)
4. 端末ベンダーは、公開鍵暗号を使った署名アルゴリズムを用いて、dm_verity_tableの署名を秘密鍵PrKで生成する
5. 端末ベンダーは、system.imgにメタデータ(dm_verity_tableおよび署名)とHash Treeを結合し(図7)、ROMに書き込むとともに、公開鍵PuKをboot.img内(Ramdiskの/verity_key)に書き込む。boot.imgには、公開鍵PuKを含むセキュアブートの署名が生成される

・端末起動後

1. boot.imgがセキュアブートされ、OSカーネルとして起動する。検証された公開鍵PuKとsystem.imgのメタデータ(root hashおよび署名)を使って署名を検証し、正しければFileSystem/systemにマウントする。boot.imgからsystem.imgへと信頼の連鎖(Chain of Trust)が構築される
2. FileSystem/systemが読み出されるたびに、ブロックごとにroot hashまでのHash Treeとのハッシュ検証を行う。ハッシュ値が違うときにはI/Oエラーを返す

 dm_verityが適用されたシステムにおいてユーザーは、マルウェアによる単純な/systemのファイル書き換えを、読み込んだブロックのハッシュ検証失敗によるI/Oエラーで検知することができる。一方で、マルウェアがdm_verityを前提として、バイナリレベルでブロックと対応するHash Treeを書き替えた場合には、起動時のroot hashの署名検証で改ざんを検知できる。また、ブロックのハッシュ値がHash Treeの対応するハッシュ値と同じになるようなブロックの値を作り出すことは、暗号学的に困難であることが知られている。

 このようにAndroid6.0からは、dm_verityとセキュアブートを組み合わせることで、Linuxカーネルだけでなく、Androidシステム層までも含めて、改ざんの検証を行うことができるようになった。

●Googleによるブートフローのガイドライン

 さて、ここまで、Androidの起動時にシステムの完全性を検証することでAndroid端末の安全性を保証する仕組みについて解説してきた。しかし、もしシステムが改ざんされていることが分かったとして、どのようなアクションを取ればよいのだろうか? 「システム改ざんが検出された時点で起動処理を中止する」という対応がまず考えられるが、ユーザーから見れば端末がなぜ起動しないのか分からないため、混乱を導く恐れがある。

 そこで、セキュアなブート処理において考慮すべきフローについて、GoogleからVerified Bootとしてガイドラインが公開されている。例えば、OSカーネルやdm_verity_tableがセキュアブートに失敗したときには、赤色の警告で検証に失敗した旨を表示することが推奨されている。

 現在販売されている全ての端末がこの新しいガイドラインに準拠しているわけではないが、今後発売される端末はこのVerified Bootに対応していくものと考えられる。これらの仕組みが活用されれば、システム改ざんを伴うような巧妙化したマルウェアへの感染にユーザーが容易に気付けるようになり、被害の拡大を防ぐことができるだろう。

●著者プロフィール
古川和快(ふるかわ かずよし)
株式会社富士通研究所 知識情報処理研究所 セキュリティ研究センター。暗号理論のソフトウェア・ハードウェア実装、モバイル機器のシステムセキュリティや製造開発におけるセキュリティ、サイバーセキュリティ対策技術の研究開発に従事。
兒島尚(こじま ひさし)
株式会社富士通研究所 知識情報処理研究所 セキュリティ研究センター。Javaを中心としたソフトウェアセキュリティ、Webアプリケーションセキュリティ、組み込み機器のセキュリティ、セキュリティテストなど、情報セキュリティ関連の研究開発に従事。OSや実行環境、ネットワーク製品などのセキュリティ脆弱性の報告多数。

最終更新:8月3日(水)6時10分

@IT