Skip to content

Most visited

Recently visited

navigation

セキュリティ対策

Android では、オペレーティング システムにセキュリティ機能を組み込むことで、アプリのセキュリティ問題が発生する頻度とその影響を大幅に低減しています。通常、デフォルトのシステム パーミッションとファイル パーミッションを使ってアプリをビルドすることにより、セキュリティに関する難しい判断を下す必要がないようにシステムは設計されています。

安全なアプリのビルドを支援する主要なセキュリティ機能には、次のようなものが含まれます。

上記のような機能が含まれていますが、このドキュメントで説明する Android セキュリティのベスト プラクティスに精通していることが重要です。これらのベスト プラクティスを一般的なコーディング手法として順守することにより、ユーザーに悪影響を及ぼすセキュリティの問題を不用意に引き起こす可能性が減少します。

データの保存

Android アプリのセキュリティに関する最も一般的な懸念は、端末で保存したデータに他のアプリがアクセスできるかどうかということです。端末でデータを保存するには、3 つの基本的な方法があります。

内部ストレージの使用

デフォルトでは、内部ストレージで作成したファイルには、アプリのみがアクセスできます。この保護は Android によって実装され、ほとんどのアプリに対して十分なものです。

通常、IPC ファイルに対しては、MODE_WORLD_WRITEABLE または MODE_WORLD_READABLE モードの使用を避ける必要があります。これらのモードは、特定のアプリへのデータアクセスを制限する機能やデータ形式の制御に対応していないからです。他のアプリのプロセスとデータを共有する必要がある場合、コンテンツ プロバイダの使用を検討してみてください。コンテンツ プロバイダは、他のアプリに読み取りと書き込みのパーミッションを与え、パーミッションを臨機応変に動的に付与します。

機密データに対する保護を強化するために、アプリが直接アクセスできないキーを使用してローカル ファイルを暗号化する場合があります。たとえば、キーを KeyStore に配置して、端末に保存されていないユーザー パスワードを使用してキーを保護することができます。この操作はルート権限の不正使用(ユーザーによるパスワードの入力を監視できる)からデータを保護しませんが、ファイル システムの暗号化を備えていない紛失した端末を保護することができます。

外部ストレージの使用

SD カードなどの外部ストレージに作成されたファフィルはグローバルに読み取りと書き込みが可能です。外部ストレージはユーザーによって削除されたり、アプリによって変更されたりする可能性があるため、外部ストレージを使用して機密情報を保存しないでください。

信頼できないソースからのデータの場合と同じように、外部ストレージからのデータを処理するときは、入力検証を実行する必要があります。動的な読み込みの前に、外部ストレージに実行可能ファイルやクラスファイルを保存しないことを強くお勧めします。アプリで外部ストレージから実行可能ファイルを取得する場合は、動的読み込みの前に、ファイルを署名して、暗号により検証する必要があります。

コンテンツ プロバイダの使用

コンテンツ プロバイダは、構造化されたストレージ メカニズムを提供します。コンテンツ プロバイダを自分のアプリのみに制限したり、エクスポートして、他のアプリからのアクセスを許可したりすることができます。他のアプリから ContentProvider にアクセスできないようにするには、アプリ マニフェストでコンテンツ プロバイダを android:exported=false とマークします。そうしない場合は、android:exported 属性を "true" に設定し、保存されたデータに他のアプリがアクセスできるようにします。

エクスポートして他のアプリで使用する ContentProvider を作成するときに、読み取りと書き込みを許可する単一のパーミッションまたは読み取りと書き込みを許可する個別のパーミッションをマニフェスト内で指定できます。パーミッションを、タスクをすぐに完了する必要があるコンテンツ プロバイダに制限することをお勧めします。通常、パーミッションを取り消して、既存のユーザーの操作を中断するよりも、後でパーミションを追加して、新しい機能を公開する方が簡単であることに注意してください。

自分のアプリのみの間でデータを共有するためにコンテンツ プロバイダを使用する場合、"signature" 保護に設定された android:protectionLevel 属性を使用することをお勧めします。署名のパーミッションには、ユーザーの確認が不要であるため、データにアクセスするアプリが同じキーで署名されている場合は、これらのパーミッションによって、より優れたユーザー エクスペリエンスを実現し、コンテンツ プロバイダのデータに対するアクセスをより確実に制限できるようになります。

さらにコンテンツ プロバイダは、android:grantUriPermissions 属性を宣言し、コンポーネントをアクティベートする Intent オブジェクトで FLAG_GRANT_READ_URI_PERMISSION および FLAG_GRANT_WRITE_URI_PERMISSION フラグを使用することにより、より細かいアクセスを可能にしています。これらのパーミッションの範囲は、 <grant-uri-permission element> によってさらに制限することができます。

コンテンツ プロバイダにアクセスするときに、query()update()delete() などのパラメータ化されたクエリメソッドを使用して、信頼できないソースからの SQL インジェクションを防止します。パラメーター化されたメソッドにユーザーデータを送信する前に、ユーザーデータを連結することにより selection 引数が作成されている場合は、パラメーター化されたメソッドを使用しても、SQL インジェクションの防止には不十分になることに注意してください。

書き込みパーミッションのセキュリティについて正しく理解するようにしてください。書き込みパーミッションでは、クリエイティブな WHERE 句を使用して結果を解析することにより、一部のデータを確認できるようにする SQL 文が許可されている点に配慮してください。たとえば、攻撃者は、特定の電話番号が既に存在している場合のみに、通話履歴の行を変更することにより、通話履歴で特定の電話番号の存在を探ることがあります。コンテンツ プロバイダ データが予測可能な構造になっている場合、書き込みパーミッションによって、読み取りと書き込みの両方のパーミッションを提供することになる可能性があります。

パーミッションの使用

Android はアプリを互いにサンドボックス化するため、アプリはリソースとデータを明示的に共有する必要があります。具体的には、ベーシック サンドボックスでは提供されない追加機能(カメラなどの端末機能へのアクセスを含む)が必要な場合は、パーミッションを宣言します。

パーミッションのリクエスト

アプリがリクエストするパーミションの数を最小限にすることをお勧めします。センシティブなパーミションにアクセスしないことにより、これらのパーミッションが誤って使用されるリスクを軽減し、ユーザーへのアプリの普及を促進し、攻撃を受けにくいアプリにすることができます。一般的には、アプリの機能にパーミッションが不要な場合は、パーミッションをリクエストしないでください。

可能な場合は、パーミッションをリクエストしないようにアプリを設計することをお勧めします。たとえば、一意の ID を作成するために端末情報へのアクセスをリクエストする代わりに、アプリの GUID を作成します(ユーザーデータの処理に関するセクションを参照してください)。または、外部ストレージ(パーミッションが必要な)を使用する代わりに、内部ストレージにデータを保存してください。

パーミッションのリクエストに加えて、アプリで <permissions> を使用して、IPC を保護することができます。IPC はセキュリティの影響を受けやすく、ContentProvider などの他のアプリに公開されます。一般的に、パーミッションはユーザーを混乱させる可能性があるため、ユーザーが確認するパーミッションではなく、アクセス コントロールを使用することをお勧めします。たとえば、単一のデベロッパーが提供するアプリの間の IPC 通信に対して、パーミッションの署名保護レベルを使用することを検討してください。

パーミッションで保護されたデータを漏洩しないでください。IPC を介してアプリがデータを公開すると、データの漏洩が発生します。IPC は、そのデータにアクセスするパーミッションがアプリにある場合にのみ利用可能です。アプリの IPC インターフェースのクライアントには、そのデータにアクセスする同じパーミションがない可能性があります。この問題の発生頻度とその潜在的な影響に関する詳細については、USENIX が発行したこちらの研究論文を参照してください。

パーミッションの作成

一般的に、セキュリティの要件を満たしながら、可能な限り少数のパーミッションを定義する必要があります。システム定義のパーミッションはさまざまな状況に対応しているため、ほとんどのアプリでは、新しいパーミッションを作成することはあまりないでしょう。必要に応じて、既存のパーミションを使用して、アクセス チェックを実行してください。

新しいパーミッションを作成する必要がある場合は、"署名" 保護レベルでタスクを完了できるかどうかを検討してください。署名パーミッションは、ユーザーに対して透過的であり、アプリがパーミッション チェックを実行しているときに、同じデベロッパーによって署名されたアプリからのアクセスのみを許可します。

"Dangerous" 保護レベルでパーミッションを作成する場合は、検討すべき複雑な点が多くあります。

これらの各ケースにおいて、デベロッパーは技術面以外で大きな課題に直面し、ユーザーの混乱を招くことにもなります。そのため、Dangerous パーミッション レベルを使用しないことをお勧めします。

ネットワークの使用

ネットワーク トランザクションではユーザーの個人的なデータが送信される場合もあるため、本質的にセキュリティに対するリスクが高くなります。特にモバイル端末がネットワーク トランザクションを実行する際のプライバシーに関する懸念は一層高まっています。そのため、ユーザーのデータを常に安全に保持するためには、すべてのベスト プラクティスをアプリに実装することが重要です。

IP ネットワークの使用

Android でネットワークを使用することは、Linux 環境でのネットワーク使用とそれほど大きな違いはありません。重要な考慮事項として、安全なウェブ トラフィック用の HttpsURLConnection など、機密データに対して適切なプロトコルを使用していることを確認する必要があります。モバイル端末は、パブリック Wi-Fi アクセス ポイントなどで、安全ではないネットワークに頻繁に接続するため、サーバーで HTTPS がサポートされている場合は常に、HTTP ではなく、HTTPS を使用することをお勧めします。

SSLSocket クラスを使用して、認証済みの暗号化されたソケットレベルの通信を簡単に実装することができます。Android 端末が Wi-Fi を使用して、安全ではないワイヤレス ネットワークにアクセスする頻度を考慮すると、ネットワークを介して通信を行うすべてのアプリで安全なネットワークを使用することを強くお勧めします。

一部のアプリが機密性の高い IPC の処理に localhost ネットワーク ポートを使用していることがあります。端末上の他のアプリがこれらのインターフェースにアクセスできるため、このアプローチはお勧めしません。その代わりに、Service などを使用した認証可能な Android IPC メカニズムを使用する必要があります(ループバックの使用よりも不適切なのは、INADDR_ANY にバインドすることです。これにより、アプリがあらゆる場所からのリクエストを受け取る可能性があります)。

一般的に重要なことですが、HTTP またはその他の安全ではないプロトコルを介してダウンロードされたデータを信頼しないようにする必要があります。また、WebView の入力と、HTTP に対して発行されたインテントへの応答を検証する必要があります。

電話ネットワークの使用

SMS プロトコルは、主にユーザー間の通信向けに設計されており、データを伝送する必要のあるアプリには適していません。SMS のこの制約のために、ウェブサーバーからユーザーの端末上のアプリにデータを送信する場合は、Google Cloud Messaging(GCM)と IP ネットワークを使用することを強くお勧めします。

ネットワークまたは端末で、SMS は暗号化されず、強力に認証されないことに注意してください。特に、SMS レシーバーでは、悪意のあるユーザーがアプリに SMS を送信する可能性があることを想定する必要があります。認証されていない SMS データを使用して、機密性の高いコマンドを実行しないでください。また、ネットワーク上で SMS がなりすましや傍受の対象になる場合があることに注意する必要があります。Android 対応端末で SMS メッセージはブロードキャスト インテントとして送信されるため、READ_SMS パーミッションを持つ他のアプリによって読み取られたり、取得されたりする可能性があります。

入力検証の実行

不十分な入力検証は、最も一般的なセキュリティ問題の 1 つですあり、アプリが実行されているプラットフォームに関係なくアプリに影響を及ぼします。Android は、アプリが入力検証の問題にさらされるリスクを低減するプラットフォームレベルの対策を備えているので、可能な限り、これらの機能を使用する必要があります。タイプセーフ言語を選択すると、入力検証の問題が発生する可能性が低くなることも認識しておいてください。

ネイティブ コードを使用している場合、ファイルから読み取ったデータ、ネットワークを介して受信したデータ、または IPC から受信したデータにより、セキュリティ問題が発生する可能性があります。最も一般的な問題は、バッファのオーバーフロー解放後使用(use after free)オフバイワン エラーです。Android は、これらのエラーの脆弱性を低下させる ASLRDEP などの多くのテクノロジーを提供しますが、こうしたテクノロジーは根本的な問題を解決するものではありません。ポインタを注意深く扱い、バッファを管理することにより、これらの脆弱性の問題を防ぐことができます。

JavaScript や SQL などの動的な文字列ベースの言語には、エスケープ文字やスクリプト インジェクションがあるため、入力検証の問題が発生する可能性があります。

SQL データベースやコンテンツ プロバイダに送信するクエリ内でデータを使用する場合、SQL インジェクションが発生することがあります。最大の防止策は、コンテンツ プロバイダに関する上記のセクションで説明したように、パラメータ化されたクエリを使用することです。また、パーミッションを読み取り専用または書き込み専用に制限すると、SQL インジェクションに関連する問題が発生する可能性を低下させることができます。

上記のセキュリティ機能を使用できない場合は、堅牢な構造のデータ形式を使用し、データが目的の形式に一致していることを確認することを強くお勧めします。文字または文字置換をブラックリストに追加することが効果的な戦略になる場合がありますが、実際には、こうした手法を使用すると、エラーが発生しやすくなるため、可能な限り使用を避ける必要があります。

ユーザーデータの処理

一般的に、ユーザーデータのセキュリティに対する最も適切なアプローチは、ユーザーの機密データや個人データにアクセスする API の使用を最小限にすることです。ユーザーデータへのアクセスが可能なときに、情報の保存や送信を避けることができる場合は、データの保存や送信を行わないでください。最後に、ハッシュや非可逆的な形式のデータを使用して、アプリのロジックを実装する方法があるかどうかを検討してください。たとえば、アプリでメールアドレスのハッシュをプリマリキーとして使用して、メールアドレスの送信や保存を回避する方法があります。これにより、誤ってデータを公開する可能性が低くなるとともに、攻撃者がアプリを侵害する可能性も低減します。

アプリがパスワードやユーザー名などの個人情報にアクセスする場合、一部の司法管轄区は、こうした個人情報の取り扱いについて説明したプライバシー ポリシーを提供するよう求める場合があることに注意してください。したがって、ユーザーデータへのアクセスを最小限にするセキュリティのベスト プラクティスにより、コンプライアンスが簡素化されます。

広告用のサードパーティ コンポーネントやアプリが使用するサードパーティ サービスなど、他のパーティにアプリが個人情報を誤って公開する場合があるかどうかについても確認する必要があります。コンポーネントやサービスが個人情報を要求する理由が不明な場合は、個人情報を提供しないでください。一般的に、アプリによる個人情報へのアクセスを減少させると、この分野で問題が発生する可能性が低くなります。

機密データへのアクセスが必要な場合、情報をサーバーに送信する必要があるかどうか、またはクライアントで操作を実行できるかどうかを検討してください。ユーザーデータの送信を避けるために、機密データを使用するコードをクライアントで実行することを検討してください。

許容度が過度に高い IPC、全ユーザーに書き込み権限があるファイル、またはネットワーク ソケットを介して、端末上の他のアプリにユーザーデータを誤って公開しないようにする必要があります。これは、パーミッションのリクエストのセクションで説明したように、パーミッションで保護されたデータの漏洩の特別なケースです。

GUID が必要な場合は、大きな一意の数値を作成して保存してください。個人情報に関連付けられている可能性がある電話番号や IMEI などの電話 ID を使用しないでください。このトピックについては、Android デベロッパー ブログで詳しく説明しています。

オンデバイス ログに書き込むときは注意してください。Android では、ログは共有リソースであり、READ_LOGS パーミッションを持つアプリで利用可能です。スマートフォンのログデータは一時的なものであり、再起動すると削除されますが、ユーザー情報を不適切にログ記録すると、ユーザーデータが知らないうちに他のアプリに漏洩する可能性があります。

WebView の使用

WebView は HTML や JavaScript が含まれている可能性のあるウェブコンテンツを読み込むため、不適切に使用すると、クロスサイトスクリプティング(JavaScriptインジェクション)など、一般的なウェブ セキュリティの問題が発生する可能性があります。Android には、WebView の機能をアプリが必要な最小限の機能に制限することにより、これらの潜在的な問題の発生を防ぐ多くのメカニズムが含まれています。

アプリが WebView 内で JavaScript を直接使用しない場合は、setJavaScriptEnabled() を呼び出さないでください。一部のサンプルコードはこのメソッド(実稼働アプリで再利用する場合があります)を使用するため、このメソッドが不要な場合は削除してください。デフォルトでは、WebView は JavaScript を実行しないため、クロスサイトスクリプティングは不可能です。

addJavaScriptInterface() を使用すると、JavaScript により、通常は Android アプリに予約されている操作が呼び出される可能性があるため、使用するときは注意してください。使用すると、すべての入力が信頼可能になるウェブページのみに addJavaScriptInterface() が公開されます。信頼できない入力が許可された場合、信頼できない JavaScript により、アプリ内で Android メソッドが呼び出し可能になることがあります。一般的に、アプリの APK 内に含まれている JavaScript のみに addJavaScriptInterface() を公開することをお勧めします。

アプリで WebView を使って機密データにアクセスする場合は、clearCache() メソッドを使用して、ローカルで保存されているファイルを削除できます。また、no-cache などのサーバー側のヘッダーを使用して、アプリが特定のコンテンツをキャッシュしてはならないことを示せます。

Android 4.4(API レベル 19)よりも前のプラットフォームを実行している端末は、多くのセキュリティ問題がある webkit のバージョンを使用しています。問題の回避策として、これらの端末でアプリが実行されている場合は、WebView オブジェクトが信頼できるコンテンツのみを表示することを確認する必要があります。また、SSL の脆弱性攻撃から保護するためにセキュリティ プロバイダをアップデートするで説明したように、アップデート可能な Provider セキュリティ オブジェクトを使用して、アプリが SSL の潜在的な脆弱性にさらされないようにする必要があります。アプリでオープンウェブのコンテンツをレンダリングする必要がある場合、最新のセキュリティ パッチを適用してアプリを最新の状態に保つために、独自のレンダラを提供することを検討してください。

認証情報の扱い

一般的に、フィッシング攻撃を検出しやすくし、成功率を下げるためには、ユーザー認証情報を求める頻度を最小限にすることをお勧めします。その代わり、認証トークンを使用して更新します。

可能な限り、端末にユーザー名とパスワードを保存しないでください。その代わりに、ユーザーが入力したユーザー名とパスワードを使用して初期認証を実行してから、一時的なサービス固有の認証トークンを使用します。

複数のアプリがアクセスできるサービスには、AccountManager を使用してアクセスする必要があります。可能な場合は、AccountManager クラスを使用して、クラウドベースのサービスを呼び出し、端末にパスワードを保存しないでください。

AccountManager を使用して Account を取得した後、認証情報を渡す前に CREATOR を確認することにより、正しくないアプリに認証情報を誤って渡すことがないようにします。

作成したアプリのみが認証情報を使用する場合は、checkSignature() を使用して、AccountManager にアクセスするアプリを確認することができます。または、1 つのアプリのみが認証情報を使用する場合は、保存のために KeyStore を使用できます。

暗号化の使用

Android は、データの分離の提供、ファイル システム全体の暗号化のサポート、安全な通信チャンネルの提供に加えて、暗号化を使用してデータを保護するためのさまざまなアルゴリズムを提供します。

一般的に、ユースケースをサポートできる、最も高いレベルの既存のフレームワーク実装を使用するようにしてください。既知の場所からファイルを安全に取得する必要がある場合は、シンプルな HTTPS URI が適切であり、暗号化の知識も必要ありません。安全なトンネルが必要な場合は、独自のプロトコルを作成するのではなく、HttpsURLConnection または SSLSocket を使用することを検討してください。

独自のプロトコルの実装が必要な場合は、独自の暗号化アルゴリズムを実装しないことを強くお勧めします。Cipher クラスで提供されている AES や RSA など、既存の暗号化アルゴリズムを使用してください。

安全な乱数ジェネレータ SecureRandom を使用して、暗号化キー KeyGenerator を初期化します。安全な乱数ジェネレータで生成されていないキーを使用すると、アルゴリズムの強度が大幅に低下し、オフライン攻撃を受ける可能性があります。

繰り返して使用するためにキーを保存する必要がある場合、長期に渡る保存と暗号化キーの取り出しを可能にする KeyStore などのメカニズムを使用してください。

プロセス間通信(IPC)の使用

一部のアプリは、ネットワーク ソケットや共有ファイルなど、Linux の従来の 手法を用いて IPC の実装を試みます。Linux の手法を使用する代わりに、IntentBinder または MessengerServiceBroadcastReceiver など、IPC 向けの Android システム機能を使用することを強くお勧めします。Android の IPC メカニズムを使用すると、IPC に接続するアプリの ID を確認し、各 IPC メカニズムにセキュリティ ポリシーを設定することができます。

IPC メカニズム間で多くのセキュリティ要素が共有されます。他のアプリで IPC メカニズムを使用しない場合、<service> 要素などのコンポーネントのマニフェスト要素で android:exported 属性を "false" に設定します。同じ UID 内の複数のプロセスで構成されるアプリの場合、または開発の終盤で、実際に機能を IPC として公開せず、コードを書き換えない場合は、このように設定すると便利です。

他のアプリが IPC にアクセスできるようにする場合、<permission> 要素を使用して、セキュリティ ポリシーを適用することができます。同じキーで署名した別のアプリ間に IPC がある場合、android:protectionLevel"signature" レベル パーミッションを使用することをお勧めします。

インテントの使用

インテントは、Android の非同期 IPC で推奨されるメカニズムです。アプリの要件に応じて、特定のアプリ コンポーネントに対して sendBroadcast()sendOrderedBroadcast()、または明示的なインテントを使用できます。

レシーバーは順序付きのブロードキャストを「消費」することができるため、これらのブロードキャストがすべてのアプリに配信されない可能性があることに注意してください。特定のレシーバーに配信する必要があるインテントを送信する場合は、nameintent によってレシーバーを宣言する明示的なインテントを使用する必要があります。

インテントの送信元は、メソッドの呼び出しで非 null パーミッションを指定して、レシーバーがパーミッションを保持していることを確認することができます。そのパーミッションを保持しているアプリのみがインテントを受け取ります。ブロードキャスト インテント内のデータが機密データである可能性がある場合、パーミッションを適用することにより、悪意のあるアプリが適切なパーミッションなしに、これらのメッセージを受信する目的で登録できないようにすることを検討してください。また、こうした状況では、ブロードキャストを実行せずに、レシーバーを直接呼び出すことも検討してください。

注: インテント フィルタはセキュリティ機能ではありません。明示的なインテントでコンポーネントを呼び出すことができますが、インテント フィルタに適合するデータがコンポーネントに含まれていないことがあります。インテント レシーバー内で入力検証を実行し、呼び出されるレシーバー、サービス、またはアクティビティに対して、入力が適切にフォーマットされていることを確認する必要があります。

サービスの使用

多くの場合、Service を使用して、他のアプリが使用する機能を提供します。各サービスクラスのマニフェスト ファイルには、対応する <service> が宣言されている必要があります。

デフォルトでは、サービスはエクスポートされず、他のアプリがサービスを呼び出すことはできません。ただし、サービスの宣言にインテント フィルタを追加した場合は、デフォルトでサービスがエクスポートされます。android:exported 属性を明示的に宣言し、エクスポートが適切に機能するようにすることをお勧めします。また、android:permission 属性を使用して、サービスを保護することができます。サービスを保護した場合、他のアプリは自身のマニフェストで対応する <uses-permission> 要素を宣言して、サービスの開始または停止やサービスへのバインドを行う必要があります。

サービスは、IPC 呼び出しの実装を実行する前に、checkCallingPermission() を呼び出すことにより、パーミッションで個々の IPC 呼び出しを保護することができます。通常、宣言型のパーミッションはエラーが発生しにくいため、マニフェストで宣言型のパーミッションを使用することをお勧めします。

バインダ インターフェースとメッセンジャー インターフェースの使用

Binder または Messenger の使用は、Android の RPC スタイル IPC で推奨されるメカニズムです。これらのインターフェースは明確に定義されたインターフェースであり、必要に応じて、エンドポイントの相互認証を有効化します。

インターフェース固有のパーミッション チェックが不要になるようにインターフェースを設計することを強くお勧めします。Binder および Messenger オブジェクトはアプリのマニフェスト内で宣言されないため、これらのオブジェクトに宣言型のパーミッションを直接適用することはできません。通常、これらのオブジェクトは、自身の実装に使用れた Service または Activity のアプリ マニフェストで宣言されたパーミッションを継承します。認証やアクセス コントロールが必要なインターフェースを作成する場合、Binder または Messenger インターフェースにこれらのコントロールをコードとして明示的に追加する必要があります。

アクセス コントロールが必要なインターフェースを提供する場合、checkCallingPermission() を使用して、呼び出し元に必要なパーミションがあるかどうかを確認してください。アプリの ID は他のインターフェースに渡されるため、呼び出し元の代理としてサービスにアクセスする前にパーミッションを確認することが特に重要になります。Service によって提供されるインターフェースを呼び出す場合、当該のサービスにアクセスするパーミッションがないと、bindService() の呼び出しに失敗する可能性があります。独自のアプリによってローカルで提供されるインターフェースを呼び出す場合、内部のセキュリティ チェックを満たす際に、clearCallingIdentity() が役立つことがあります。

サービスでの IPC の実行に関する詳細については、バインドされたサービスを参照してください。

ブロードキャスト レシーバーの使用

BroadcastReceiver は、Intent によって開始された非同期リクエストを処理します。

デフォルトでは、レシーバーはエクスポートされ、他のアプリによって呼び出すことができます。他のアプリで BroadcastReceiver を使用する場合は、アプリ マニフェスト内で <receiver> 要素を使用して、レシーバーにセキュリティ パーミッションを適用することができます。このようにすると、適切なパーミッションがないアプリがインテントを BroadcastReceiver に送信しなくなります。

コードの動的読み込み

アプリの APK の外部からコードを読み込まないことを強くお勧めします。外部からコードを読み込むと、コード インジェクションやコード改ざんによりアプリが侵害される可能性が大幅に高まります。また、バージョン管理やアプリのテストが複雑になります。さらに、アプリの動作を確認できなくなる可能性があるため、一部の環境では、APK の外部からのコード読み込みが禁止されています。

アプリが動的にコードを読み込む場合、動的に読み込まれたコードに関して特に注意する必要があるのは、アプリの APK と同じセキュリティ パーミッションでコードが実行されることです。ユーザーは、アプリのデベロッパーの ID に基づいて、アプリをインストールすることを決め、動的に読み込まれるコードを含めて、アプリ内で実行されるコードが提供されることを想定しています。

動的に読み込まれたコードに関連する主要なセキュリティ リスクは、確認可能なソースからコードが提供されていない場合に発生します。APK 内にモジュールが直接含まれている場合、他のアプリはこのモジュールを変更できません。コードがネイティブ ライブラリであっても、DexClassLoader を使用してクラスが読み込まれた場合であっても、このモジュールを変更することはできません。暗号化されていないプロトコルを介してネットワークからダウンロードされた、または全ユーザーに書き込み権限がある外部ストレージなどの場所からダウンロードされたコードなど、安全ではない場所からコードの読み込みを試行する多くのアプリの例があります。これらの場所では、ネットワーク上の誰かが送信中のコンテンツを改変したり、ユーザーの端末上の別のアプリが端末のコンテンツを改変したりする可能性があります。

仮想マシンのセキュリティ

Dalvik は、Android のランタイム仮想マシン(VM)です。Dalvik は Android 向けに特別にビルドされていますが、他の仮想マシンのソースコードに関する多くの懸念事項が Android にも当てはまります。一般的に、仮想マシンに関連するセキュリティ問題については心配する必要はありません。アプリは安全なサンドボックス環境で実行されるため、システムの他のプロセスはアプリのコードや個人データにアクセスすることはできません。

仮想マシンのセキュリティ問題について詳しく調べる場合は、この問題に関する既存のリソースやドキュメントを十分に確認しておくことをお勧めします。一般的なリソースについては、次の URL を参照してください。

このドキュメントでは、Android 固有の領域や他の VM 環境とは異なる領域に重点を置いて説明しています。他の環境での VM プログラミングの経験があるデベロッパーの場合、Android アプリの記述について違いを感じる可能性のある大きな問題が 2 つあります。

ネイティブ コードのセキュリティ

一般的に、Android NDK でネイティブ コードを使用するのではなく、アプリの開発には Android SDK を使用することをお勧めします。ネイティブ コードでビルドされたアプリは、より複雑で、移植性が低く、バッファのオーバーフローなど、一般的なメモリ破損エラーが含まれる可能性が高くなります。

Android は Linux kernel を使用して構築されるため、Linux の開発で使用されるセキュリティのベスト プラクティスに精通していると、ネイティブ コードを使用する際に特に役立ちます。このドキュメントでは Linux のセキュリティ プラクティスについて説明しませんが、最も一般的なリソースの 1 つは「Secure Programming for Linux and Unix HOWTO」(http://www.dwheeler.com/secure-programs)です。

Android 環境と大部分の Linux 環境との重要な違いは、アプリケーション サンドボックスです。Android では、ネイティブ コードで記述されたアプリを含めて、すべてのアプリがアプリケーション サンドボックスで実行されます。出発点として、Linux に精通しているデベロッパーが理解すべきことは、一意の UID と非常に限定的なパーミッションがすべてのアプリに付与されることです。これについては、Android セキュリティの概要で詳しく説明しています。また、ネイティブ コードを使用する場合でも、アプリのパーミッションについて熟知している必要があります。

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

WeChat で Google Developers をフォローする

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience. (Dec 2017 Android Platform & Tools Survey)