セキュリティの実装

Android セキュリティ チームには、Android デバイスにおけるセキュリティ上の潜在的な問題の防止に関する情報のリクエストが定期的に寄せられます。また、不定期にデバイスのスポット チェックを行い、デバイスのメーカーや影響を受けるパートナーに、潜在的な問題について知らせています。

このページには、Google の経験に基づくセキュリティに関するおすすめの方法が記載されています。これは開発者向けの設計セキュリティ ガイドの内容を拡張したものです。また、このページではデバイス上でシステムレベルのソフトウェアを構築またはインストールする場合に特有の詳細情報も記載されています。

上記おすすめの方法の採用を促進するため、Android セキュリティ チームは Android 互換性テストスイート(CTS)と Android Lint にテストを統合しています。デバイスの実装者は、他の Android ユーザーにとって有用なテストを提供することが推奨されます(root/cts/tests/tests/security/src/android/security/cts のセキュリティ関連テストをご覧ください)。

開発プロセス

開発プロセスと開発環境では、次のおすすめの方法を使用します。

ソースコードを確認する

ソースコードのレビューでは、このドキュメントに掲載されているような広範なセキュリティ問題を検出できます。手動と自動の両方でのソースコードのレビューを強くおすすめします。ポイント:

  • Android SDK を使用してすべてのアプリコードに Android Lint を実行し、特定された問題を修正します。
  • バッファ オーバーフローや off-by-one エラーなど、メモリ管理の問題を検出できる自動ツールを使用してネイティブ コードを分析する必要があります。
  • Android ビルドシステムは、AddressSanitizer や UndefinedBehaviorSanitizer など、この目的で使用できる多くの LLVM サニタイザをサポートしています。

自動テストを使用

自動テストでは、以下で紹介している問題などの広範なセキュリティ問題を検出できます。ポイント:

  • CTS のセキュリティ テストは随時更新されています。CTS の最新バージョンを実行して互換性を確認してください。
  • 開発プロセス全体を通じて CTS を定期的に実行することで、問題を早期発見し、修正までの時間を短縮します。Android では 1 日に何度も行われる自動ビルドプロセスで CTS を継続的インテグレーションの一環として使用しています。
  • デバイス メーカーはインターフェースのセキュリティ テストを自動化してください。不正入力のテスト(ファズテスト)などがこれに該当します。

システム イメージの署名

システム イメージの署名は、デバイスの整合性を決定する際に重要です。ポイント:

  • デバイスには、公開されている鍵で署名してはいけません。
  • デバイスの署名に使用される鍵は、制限付きで監査可能なアクセスを提供するハードウェア セキュリティ モジュール(HSM)など、業界標準に従った機密鍵の取り扱い方法により管理します。

アプリの署名(APK)

アプリ署名はデバイスのセキュリティで重要な役割を果たし、権限の確認やソフトウェアの更新に使用されます。アプリ署名に使用する鍵を選択する際は、アプリが 1 つのデバイスでのみ利用されるのか、複数のデバイスにまたがって使用されるのかを考慮することが重要です。ポイント:

  • アプリには、公開されている鍵で署名してはいけません。
  • アプリの署名に使用される鍵は、制限付きで監査可能なアクセスを提供する HSM など、業界標準に従った機密鍵の取り扱い方法により管理します。
  • アプリには、プラットフォーム キーで署名するべきではありません。
  • 同じパッケージ名のアプリを異なる鍵で署名しないようにしてください。これは、プラットフォーム キーを使用する場合など、さまざまなデバイス用にアプリを作成する場合によく発生します。アプリがデバイスに依存しない場合は、デバイス間で同じ鍵を使用します。アプリがデバイス固有の場合は、デバイスと鍵ごとに固有のパッケージ名を作成します。

アプリを公開する

Google Play では、デバイスのメーカーは完全なシステム アップデートを行わずにアプリを更新できます。これにより、セキュリティ問題への迅速な対応や新しい機能の提供ができるようになり、またアプリのパッケージが一意になるようにすることもできます。ポイント:

  • アプリを Google Play にアップロードすると、完全な無線(OTA)アップデートを行わずに自動更新できます。アップロードされたものの公開されていないアプリをユーザーが直接ダウンロードすることはできませんが、アプリは引き続き更新されます。以前にこのアプリをインストールしたユーザーは、このアプリの再インストールや、他のデバイスへのインストールが可能です。
  • 会社の商標を使用するなどの方法により、会社に明示的に関連付けられたアプリ パッケージ名を作成します。
  • 第三者のユーザーによるパッケージ名のなりすましを防ぐため、デバイスのメーカーが公開するアプリは Google Play ストアにアップロードする必要があります。デバイスのメーカーが、アプリを Play ストアで公開せずにデバイスにインストールした場合、別のデベロッパーが同じアプリをアップロードし、同じパッケージ名を使用して、アプリのメタデータを変更することが可能となります。このアプリがユーザーに提示された場合、この関連性のないメタデータが原因で混乱が生じることがあります。

インシデントへの対応

デバイス固有のセキュリティ問題が発生した場合に、外部の当事者がデバイスのメーカーに問い合わせできる必要があります。セキュリティ インシデントを管理するために、一般公開用のメールアドレスを作成することをおすすめします。ポイント:

  • security@your-company.com のようなアドレスを作成して公開します。
  • Android OS や複数のデバイス メーカー製の Android デバイスに影響するセキュリティ上の問題に気付いた場合は、セキュリティ バグレポートを使用して Android セキュリティ チームにお問い合わせください。

プロダクトの実装

プロダクトの実装時には、次のおすすめの方法を使用します。

ルートプロセスを分離

ルートプロセスは、権限昇格攻撃で最も狙われるターゲットです。そのため、ルートプロセスの数を減らすと、権限昇格のリスクが減少します。CTS には、ルートプロセスを一覧表示する情報テストが含まれています。ポイント:

  • デバイスはルートとして最低限必要なコードを実行するようにしてください。できるだけルートプロセスではなく通常の Android プロセスを使用します。ICS Galaxy Nexus のルートプロセスは vold、inetd、zygote、tf_daemon、ueventd、init の 6 つだけです。プロセスをデバイスでルートとして実行する必要がある場合は、公開でレビューができるようにプロセスを AOSP 機能リクエストで文書化します。
  • 可能であれば、ルートコードは信頼できないデータから分離し、IPC を介してアクセスするようにします。たとえば、ルート機能を Binder 経由でアクセスできる小規模なサービスに縮小し、そのサービスに署名権限を与えて、ネットワーク トラフィックを処理する特権の低い(または特権を持たない)アプリに公開します。
  • ルートプロセスはネットワーク ソケットでリッスンしないでください。
  • ルートプロセスには、Java VM などのアプリ用汎用ランタイムを含めないでください。

システムアプリを分離

一般的に、プリインストールされたアプリを共有システムの UID で実行してはいけません。しかし、アプリがシステムまたは別の特権サービスの共有 UID を使用する必要がある場合は、ユーザーがインストールしたサードパーティ アプリからアクセスできるサービス、ブロードキャスト レシーバ、コンテンツ プロバイダをアプリでエクスポートしないでください。ポイント:

  • デバイスはシステムとして最低限必要なコードを実行する必要があります。可能であれば、システム UID を再使用するのではなく、独自の UID を保有する Android プロセスを使用します。
  • 可能であれば、システムコードは信頼できないデータから分離し、IPC は他の信頼できるプロセスにのみ公開します。
  • システム プロセスは、ネットワーク ソケットでリッスンしないでください。

プロセスを分離

Android アプリ サンドボックスは、アプリがルートプロセスやデバッガなど、システム上の他のプロセスと分離していることを想定しています。デバッグがアプリとユーザーによって特に有効にされていない限り、アプリはその想定に反しないようにする必要があります。ポイント:

  • ドキュメント化された Android のデバッグ方法を使用しない場合は、ルートプロセスが個々のアプリデータ フォルダ内にあるデータにアクセスしないようにします。
  • ドキュメント化された Android のデバッグ方法を使用しない場合は、ルートプロセスがアプリのメモリにアクセスしないようにしてください。
  • 他のアプリやプロセスのデータやメモリにアクセスするアプリがデバイスに含まれないようにしてください。

SUID ファイルの保護

信頼できないプログラムが新しい setuid プログラムにアクセスできないようにしてください。setuid プログラムにはルートアクセスを可能にする脆弱性が生じることが多いため、信頼できないアプリケーションが setuid プログラムを利用する可能性を最小限に抑えてください。ポイント:

  • SUID プロセスには、Android セキュリティ モデルを回避可能にするためのシェルやバックドアを指定しないでください。
  • SUID プログラムはどのユーザーからも書き込みできないようにする必要があります。
  • SUID プログラムは、誰でも読み取りや実行ができる状態にしてはいけません。グループを作成し、そのグループのメンバーに対して SUID バイナリへのアクセスを制限して、SUID プログラムを実行できるアプリをそのグループに配置します。
  • SUID プログラムは、デバイスのユーザー ルーティングの一般的なソースです。このリスクを軽減するため、シェルユーザーが SUID プログラムを実行できないようにする必要があります。

CTS 検証ツールには SUID ファイルの情報テストリストが含まれています。一部の setuid ファイルは CTS テストで許可されません。

リスニング ソケットを保護

デバイスが任意のインターフェース上の任意のポートでリッスンしている場合、CTS テストは失敗します。エラーが発生した場合、Android は次のおすすめの方法が使用されているか確認します。

  • デバイスにリスニング ポートがないようにする必要があります。
  • リスニング ポートは OTA なしで無効にできなければなりません。これは、サーバーまたはユーザー デバイスの構成の変更により行います。
  • ルートプロセスはどのポートでもリッスンしないでください。
  • システム UID が所有するプロセスはどのポートでもリッスンしないでください。
  • ソケットを使用するローカル IPC では、アプリは特定のグループにアクセスを限定した UNIX ドメインのソケットを使用する必要があります。IPC 用のファイル記述子を作成し、特定の UNIX グループに対して +RW にします。すべてのクライアント アプリはその UNIX グループに属している必要があります。
  • 無線通信やモデムがアプリのプロセッサとは別になっているような、複数のプロセッサを搭載したデバイスではプロセッサ間の通信にネットワーク ソケットを利用するものもあります。そのような場合、プロセッサ間の通信に利用されるネットワーク ソケットでは分離したネットワーク インターフェースを使い、デバイス上の権限のないアプリによるアクセスを防ぎます(iptables を使用して、デバイス上の他のアプリによるアクセスを防ぎます)。
  • リスニング ポートを処理するデーモンは、不正な形式のデータに対して堅牢である必要があります。 Google は、許可されていないクライアントと、可能であれば許可されたクライアントを使用して、ポートに対してファズテストを実行する場合があります。クラッシュは所定の重大度のバグとして報告されます。

ログデータ

データをログに記録すると、そのデータの漏洩リスクが高まり、また、システムのパフォーマンスが低下します。Android デバイスにデフォルトでインストールされているアプリが重要なユーザーデータをログに記録した結果発生したセキュリティ インシデントが複数報告されています。ポイント:

  • アプリやシステム サービスは、機密情報を含んでいる可能性のあるサードパーティ アプリから取得したデータをログに記録するべきではありません。
  • アプリが通常の動作の一環として個人情報(PII)のログを記録しないようにする必要があります。

CTS にはシステムログ内に機密情報の可能性がある情報が存在するかどうかを確認するテストが含まれます。

ディレクトリ アクセスの制限

グローバルに書き込み可能なディレクトリでは、セキュリティ上の弱点が生じ、信頼されているファイルの名前の変更、ファイルの置き換え、シンボリック リンク ベースの攻撃(攻撃者はファイルへのシンボリック リンクを使用して信頼されているプログラムをだまし、本来想定されていない処理を実行させる)をアプリができるようにする可能性があります。また、書き込み可能なディレクトリでは、アプリをアンインストールしても、アプリに関連付けられたすべてのファイルを適切にクリーンアップできないことがあります。

システムまたは root ユーザーにより作成されたディレクトリは、グローバルに書き込み可能にしないことをおすすめします。CTS テストでは、既知のディレクトリをテストすることによりこのおすすめの方法が強制適用されます。

構成ファイルの保護

多くのドライバとサービスは、/system/etc/data などのディレクトリに保存されている構成ファイルとデータファイルに依存しています。これらのファイルが特権プロセスにより処理され、グローバルに書き込み可能である場合、アプリが悪意のあるコンテンツをこのグローバルに書き込み可能なファイルに作成することによって、このプロセスの脆弱性を悪用することが可能となります。ポイント:

  • 特権プロセスによって使用される構成ファイルは、誰でも読み取れるようにはしないでください。
  • 特権プロセスによって使用される構成ファイルは、グローバルに書き込み可能にしてはいけません。

ネイティブ コード ライブラリを保存

デバイス メーカーの特権プロセスで使用されるコードは、/vendor または /system に配置してください。これらのファイル システムは起動時に読み取り専用としてマウントされます。システムが使用するライブラリまたはデバイスにインストールされたその他の高い権限を持つアプリが使用するライブラリも、これらのファイル システムに配置することをおすすめします。これにより、特権プロセスが実行するコードを攻撃者が制御できるようになるセキュリティの脆弱性を回避できます。

デバイス ドライバへのアクセスを制限する

ドライバに直接アクセスできるのは信頼されたコードのみにする必要があります。可能であれば、推奨されるアーキテクチャは、プロキシが呼び出す単一目的のデーモンをドライバに対して指定し、ドライバにはそのデーモンしかアクセスできないよう制限することです。おすすめの方法として、ドライバ デバイス ノードは誰でも読み取りや書き込みができる状態にはしないでください。CTS テストでは、公開されているドライバの既知のインスタンスをチェックすることにより、このおすすめの方法が強制適用されます。

ADB を無効にする

Android Debug Bridge(adb)は重要な開発およびデバッグ用ツールですが、管理された安全な環境で使用することが想定されていますので、通常の使用時には有効にしないでください。ポイント:

  • ADB はデフォルトで無効にする必要があります。
  • 接続を承認する前に、ユーザーが ADB をオンにする必要があります。

ブートローダーのロック解除

多くの Android デバイスはロック解除をサポートしており、これによりデバイスの所有者がシステム パーティションの変更や、カスタム オペレーティング システムのインストールを行うことができます。一般的な例として、サードパーティの ROM をインストールし、デバイスでシステムレベルの開発を行うことが挙げられます。たとえば、Google Nexus デバイスのオーナーは fastboot oem unlock を実行してロック解除プロセスを開始できます。このとき次のメッセージがユーザーに表示されます。

Unlock bootloader?

ブートローダーのロックを解除すると、このデバイスにカスタム オペレーティング システム ソフトウェアをインストールできます。

カスタム OS は、元の OS と同じテストの対象ではなく、お使いのデバイスやインストール済みのアプリが正常に動作しなくなる可能性があります。

個人データへの不正なアクセスを防ぐため、ブートローダーのロックを解除すると、デバイスからの個人データもすべて削除(データの初期化)されます。

音量大 / 小ボタンを押して [Yes] または [No] を選択し、電源ボタンを押して続行します。

Yes: ブートローダーのロックを解除します(保証が無効になる場合があります)。

No: ブートローダーのロックの解除およびデバイスの再起動を行いません。


ロック解除可能な Android デバイスはロック解除前にすべてのユーザーデータを安全に消去することをおすすめします。ロック解除時にすべてのデータを適切に削除しないと、物理的に近接した攻撃者が機密情報である Android ユーザーデータへのアクセスを不正に行う可能性があります。ユーザーデータの開示を防止するには、ロック解除をサポートするデバイスに適切にロック解除が実装されている必要があります(デバイスのメーカーによるロック解除の実装が適切でない事例が多くあります)。適切に実装されたロック解除プロセスには、次のプロパティがあります。

  • ユーザーがロック解除コマンドを確認したら、デバイスがすぐにデータのワイプを開始する必要があります。安全に削除が完了するまで、unlocked フラグを設定しないでください。
  • 安全に削除を完了できない場合、デバイスはロックされた状態のままでなければなりません。
  • ioctl(BLKSECDISCARD) または同等のものが下位のブロック デバイスでサポートされている場合は、これを使用する必要があります。eMMC デバイスでは、Secure Erase または Secure Trim コマンドを使用します。eMMC 4.5 以降の場合は、通常の Erase または Trim に続いて Sanitize 操作を使用します。
  • BLKSECDISCARD が下位のブロック デバイスでサポートされていない場合、ioctl(BLKDISCARD) を代わりに使用する必要があります。eMMC デバイスでは、通常の Trim 操作を行います。
  • BLKDISCARD がサポートされていない場合、ブロック デバイスをすべてゼロで上書きすることは許容されます。
  • エンドユーザーが、パーティションをフラッシュする前のユーザーデータのワイプを必須にできるようにしなければなりません。たとえば、Nexus デバイスの場合は、fastboot oem lockコマンドを使用します。
  • デバイスは、eFuse または同様のメカニズムを使用して、デバイスのロック解除や再ロックが行われたかどうかを記録できます。

上記の要件により、ロック解除操作が完了すると、すべてのデータが破棄されます。これらの保護を実装していない場合は、中レベルのセキュリティ脆弱性があると見なされます。

ロック解除されたデバイスを再度ロックするには fastboot oem lock コマンドを使用します。ブートローダーをロックすると、元のデバイス メーカーの OS と同じように、新しいカスタム OS によりユーザーデータが保護されます。たとえば、デバイスのロックが再度解除された場合はユーザーデータが消去されます。