セキュリティの実装

Android セキュリティ チームは、Android デバイス上の潜在的なセキュリティ問題の防止に関する情報のリクエストを定期的に受けています。また、時々デバイスを抜き取りチェックし、デバイスのメーカーや影響を受けるパートナーに潜在的な問題を知らせます。

このページでは、当社の経験に基づいたセキュリティのベスト プラクティスを提供し、開発者向けに提供したセキュリティの設計ドキュメントを拡張し、デバイス上でのシステム レベルのソフトウェアの構築またはインストールに特有の詳細が含まれています。

これらのベスト プラクティスの導入を促進するために、Android セキュリティ チームは可能な限りテストをAndroid Compatibility Test Suite (CTS) およびAndroid Lintに組み込んでいます。デバイス実装者には、他の Android ユーザーに役立つテストを提供することをお勧めします (セキュリティ関連のテストroot/cts/tests/tests/security/src/android/security/ctsでご覧ください)。

開発プロセス

開発プロセスおよび環境では、次のベスト プラクティスを使用してください。

ソースコードのレビュー

ソース コード レビューでは、このドキュメントで特定された問題を含む、幅広いセキュリティ問題を検出できます。 Android では、手動と自動の両方のソース コード レビューを強く推奨しています。ベストプラクティス:

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

自動テストの使用

自動テストでは、以下で説明するいくつかの問題を含む、幅広いセキュリティ問題を検出できます。ベストプラクティス:

  • CTS はセキュリティ テストによって定期的に更新されます。最新バージョンの CTS を実行して互換性を確認します。
  • 開発プロセス全体を通じて CTS を定期的に実行して、問題を早期に検出し、修正までの時間を短縮します。 Android は、1 日に複数回ビルドする自動ビルド プロセスの継続的統合の一環として CTS を使用します。
  • デバイス メーカーは、不正な入力によるテスト (ファズ テスト) を含む、インターフェイスのセキュリティ テストを自動化する必要があります。

システムイメージへの署名

システム イメージの署名は、デバイスの完全性を判断するために重要です。ベストプラクティス:

  • デバイスは、公に知られているキーで署名されてはなりません。
  • デバイスの署名に使用されるキーは、制限された監査可能なアクセスを提供するハードウェア セキュリティ モジュール (HSM) など、機密キーを処理するための業界標準の慣行と一致する方法で管理する必要があります。

アプリケーション (APK) に署名する

アプリケーション署名はデバイスのセキュリティにおいて重要な役割を果たし、ソフトウェアの更新だけでなく権限のチェックにも使用されます。アプリケーションの署名に使用するキーを選択するときは、アプリケーションが単一のデバイスでのみ使用できるのか、それとも複数のデバイス間で共通に使用できるのかを考慮することが重要です。ベストプラクティス:

  • アプリケーションは、公に知られているキーを使用して署名してはなりません。
  • アプリケーションの署名に使用されるキーは、制限付きの監査可能なアクセスを提供する HSM など、機密キーを処理するための業界標準の慣行と一致する方法で管理する必要があります。
  • アプリケーションはプラットフォーム キーを使用して署名しないでください。
  • 同じパッケージ名のアプリケーションを異なるキーで署名しないでください。これは、さまざまなデバイス用のアプリケーションを作成する場合、特にプラットフォーム キーを使用する場合によく発生します。アプリケーションがデバイスに依存しない場合は、デバイス間で同じキーを使用します。アプリケーションがデバイス固有の場合は、デバイスおよびキーごとに一意のパッケージ名を作成します。

アプリケーションの公開

Google Play は、デバイス メーカーに、完全なシステム アップデートを実行せずにアプリケーションをアップデートできる機能を提供します。これにより、セキュリティ問題への対応や新機能の提供が迅速化されるほか、アプリケーションに一意のパッケージ名を付ける方法も提供されます。ベストプラクティス:

  • アプリケーションを Google Play にアップロードすると、完全な無線 (OTA) アップデートを必要とせずに自動アップデートが可能になります。アップロードされたものの未公開のアプリケーションは、ユーザーが直接ダウンロードすることはできませんが、アプリケーションは引き続き更新されます。以前にアプリをインストールしたことがあるユーザーは、再インストールしたり、他のデバイスにインストールしたりできます。
  • 会社の商標を使用するなどして、会社と明確に関連付けられるアプリケーション パッケージ名を作成します。
  • デバイスのメーカーが公開したアプリケーションは、サードパーティ ユーザーによるパッケージ名の偽装を避けるために、Google Play ストアにアップロードする必要があります。デバイスのメーカーが Play ストアでアプリを公開せずにデバイスにアプリをインストールした場合、別の開発者が同じアプリをアップロードし、同じパッケージ名を使用し、アプリのメタデータを変更する可能性があります。アプリがユーザーに表示されるとき、この無関係なメタデータにより混乱が生じる可能性があります。

インシデントへの対応

外部関係者は、デバイス固有のセキュリティ問題についてデバイスの製造元に連絡できる必要があります。セキュリティ インシデントを管理するために、一般にアクセスできる電子メール アドレスを作成することをお勧めします。ベストプラクティス:

  • security@your-company.comまたは同様のアドレスを作成し、公開します。
  • Android OS または複数のデバイス メーカーの Android デバイスに影響を与えるセキュリティ問題に気付いた場合は、セキュリティ バグ レポートを提出して Android セキュリティ チームに連絡する必要があります。

製品の導入

製品を実装するときは、次のベスト プラクティスを使用してください。

ルートプロセスの分離

ルート プロセスは権限昇格攻撃の最も頻繁なターゲットであるため、ルート プロセスの数を減らすと権限昇格のリスクが軽減されます。 CTS には、ルート プロセスをリストする情報テストが含まれています。ベストプラクティス:

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

システムアプリの分離

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

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

プロセスの分離

Android アプリケーション サンドボックスは、ルート プロセスやデバッガーなど、システム上の他のプロセスから分離されることを期待してアプリケーションを提供します。アプリケーションとユーザーによってデバッグが特に有効化されていない限り、アプリケーションはその期待に違反すべきではありません。ベストプラクティス:

  • 文書化された Android デバッグ方法を使用しない限り、ルート プロセスは個々のアプリケーション データ フォルダー内のデータにアクセスしてはなりません。
  • 文書化された Android デバッグ方法を使用しない限り、ルート プロセスはアプリケーションのメモリにアクセスしてはなりません。
  • デバイスには、他のアプリケーションやプロセスのデータやメモリにアクセスするアプリケーションを含めてはなりません。

SUID ファイルの保護

新しい setuid プログラムは、信頼できないプログラムからアクセスできないようにする必要があります。 Setuid プログラムには、root アクセスを取得するために使用できる脆弱性が存在することがよくあるため、信頼できないアプリケーションによる 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 デバッグ ブリッジ (adb) は貴重な開発およびデバッグ ツールですが、制御された安全な環境で使用するように設計されているため、一般的な使用には有効化しないでください。ベストプラクティス:

  • ADB はデフォルトで無効にする必要があります。
  • ADB では、接続を受け入れる前にユーザーが ADB をオンにすることを要求する必要があります。

ブートローダーのロックを解除する

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

ブートローダーのロックを解除しますか?

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

カスタム OS は元の OS と同じテストの対象ではないため、デバイスやインストールされているアプリケーションが正常に動作しなくなる可能性があります。

個人データへの不正アクセスを防ぐために、ブートローダーのロックを解除すると、デバイスからすべての個人データも削除されます (「データの工場出荷時設定へのリセット」)。

音量を上げる/下げるボタンを押して「はい」または「いいえ」を選択します。次に、電源ボタンを押して続行します。

はい: ブートローダーのロックを解除します (保証が無効になる可能性があります)

いいえ: ブートローダーのロックを解除してデバイスを再起動しません。


ベスト プラクティスとして、ロック解除可能な Android デバイスは、ロックを解除する前にすべてのユーザー データを安全に消去する必要があります。ロック解除時にすべてのデータを適切に削除しないと、物理的に近接した攻撃者が Android ユーザーの機密データに不正にアクセスできる可能性があります。ユーザー データの漏洩を防ぐには、ロック解除をサポートするデバイスがロック解除を適切に実装する必要があります (デバイス メーカーがロック解除を不適切に実装した例を多数見てきました)。適切に実装されたロック解除プロセスには次の特性があります。

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

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

ロックが解除されたデバイスは、 fastboot oem lockコマンドを使用して後で再ロックできます。ブートローダーをロックすると、元のデバイス製造元の OS で利用可能であったのと同じユーザー データの保護が新しいカスタム OS で提供されます (たとえば、デバイスが再びロック解除されるとユーザー データは消去されます)。