Android Applications Basics
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
二つの層があります:
OSは、インストールされたアプリケーションを互いに隔離します。
アプリケーション自体は、開発者が特定の機能を公開し、アプリケーションの機能を設定することを可能にします。
各アプリケーションには特定のユーザーIDが割り当てられます。これはアプリのインストール時に行われ、アプリはそのユーザーIDが所有するファイルまたは共有ファイルとしか相互作用できません。したがって、アプリ自体、OSの特定のコンポーネント、およびルートユーザーのみがアプリのデータにアクセスできます。
二つのアプリケーションは同じUIDを使用するように設定できます。これは情報を共有するのに便利ですが、一方が侵害されると両方のアプリケーションのデータが侵害されることになります。これがこの動作が推奨されない理由です。
同じUIDを共有するには、アプリケーションはマニフェスト内で同じandroid:sharedUserId
値を定義する必要があります。
Androidアプリケーションサンドボックスは、各アプリケーションを別のユーザーIDの下で別のプロセスとして実行することを可能にします。各プロセスは独自の仮想マシンを持っているため、アプリのコードは他のアプリから隔離されて実行されます。 Android 5.0(L)以降、SELinuxが強制されます。基本的に、SELinuxはすべてのプロセス間の相互作用を拒否し、その後、期待される相互作用のみを許可するポリシーを作成しました。
アプリをインストールするときにアプリが権限を要求する場合、アプリはAndroidManifest.xmlファイル内の**uses-permission
要素に設定された権限を要求しています。uses-permission要素は、name属性内で要求された権限の名前を示します。また、maxSdkVersion属性もあり、指定されたバージョンよりも高いバージョンでは権限の要求を停止します。
Androidアプリケーションは最初にすべての権限を要求する必要はなく、動的に権限を要求することもできますが、すべての権限はマニフェストに宣言されている必要があります。**
アプリが機能を公開する場合、特定の権限を持つアプリのみにアクセスを制限することができます。 権限要素には三つの属性があります:
権限の名前
関連する権限をグループ化するためのpermission-group属性。
権限がどのように付与されるかを示すprotection-level。四種類あります:
Normal: アプリに既知の脅威がない場合に使用されます。ユーザーは承認する必要はありません。
Dangerous: この権限が要求されたアプリケーションに昇格したアクセスを付与することを示します。ユーザーに承認を求められます。
Signature: コンポーネントをエクスポートするのと同じ証明書で署名されたアプリのみが権限を付与されます。これは最も強力な保護タイプです。
SignatureOrSystem: コンポーネントをエクスポートするのと同じ証明書で署名されたアプリまたはシステムレベルのアクセスで実行されているアプリのみが権限を付与されます。
これらのアプリは一般的に**/system/app
または/system/priv-app
ディレクトリにあり、その中には最適化されたものもあります(classes.dex
ファイルが見つからないこともあります)。これらのアプリケーションは、時には過剰な権限で実行されている**ため、確認する価値があります(ルートとして)。
AOSP(Android OpenSource Project)ROMに付属しているもの
デバイスの製造元によって追加されたもの
携帯電話のプロバイダーによって追加されたもの(彼らから購入した場合)
物理的なAndroidデバイスにルートアクセスを取得するには、一般的に1つまたは2つの脆弱性を悪用する必要があります。これらは通常、デバイスおよびバージョンに特有です。
エクスプロイトが成功すると、通常、Linuxのsu
バイナリがユーザーのPATH環境変数に指定された場所(例:/system/xbin
)にコピーされます。
suバイナリが設定されると、別のAndroidアプリがsu
バイナリとインターフェースし、ルートアクセスのリクエストを処理します。例えば、SuperuserやSuperSU(Google Playストアで入手可能)などです。
ルート化プロセスは非常に危険であり、デバイスに深刻な損傷を与える可能性があることに注意してください。
カスタムファームウェアをインストールすることでOSを置き換えることが可能です。これにより、古いデバイスの有用性を拡張したり、ソフトウェア制限を回避したり、最新のAndroidコードにアクセスしたりすることができます。 OmniROMやLineageOSは、使用するための最も人気のあるファームウェアの二つです。
カスタムファームウェアをインストールするためにデバイスをルート化する必要はないことに注意してください。一部の製造元は、文書化され、安全な方法でブートローダーのロック解除を許可しています。
デバイスがルート化されると、任意のアプリがルートとしてアクセスを要求できます。悪意のあるアプリケーションがそれを取得すると、ほぼすべてにアクセスでき、電話を損傷させることができます。
Androidアプリケーションの形式は_ APKファイル形式_と呼ばれます。基本的にはZIPファイルです(ファイル拡張子を.zipに変更することで、内容を抽出して表示できます)。
APKの内容(網羅的ではありません)
AndroidManifest.xml
resources.arsc/strings.xml
resources.arsc: バイナリXMLのようなプリコンパイルされたリソースを含みます。
res/xml/files_paths.xml
META-INF/
ここに証明書が存在します!
classes.dex
Dalvikバイトコードを含み、アプリケーションがデフォルトで実行するコンパイルされたJava(またはKotlin)コードを表します。
lib/
CPUアーキテクチャごとにサブディレクトリに分けられたネイティブライブラリを格納します。
armeabi
: ARMベースのプロセッサ用のコード
armeabi-v7a
: ARMv7およびそれ以降のプロセッサ用のコード
x86
: X86プロセッサ用のコード
mips
: MIPSプロセッサ専用のコード
assets/
アプリに必要な雑多なファイルを格納し、追加のネイティブライブラリやDEXファイルを含む可能性があり、時にはマルウェア作成者が追加のコードを隠すために使用します。
res/
resources.arscにコンパイルされていないリソースを含みます。
Android開発では、JavaまたはKotlinがアプリ作成に使用されます。デスクトップアプリのようにJVMを使用する代わりに、AndroidはこのコードをDalvik実行可能(DEX)バイトコードにコンパイルします。以前は、Dalvik仮想マシンがこのバイトコードを処理していましたが、現在では新しいAndroidバージョンではAndroid Runtime(ART)が引き継いでいます。
リバースエンジニアリングでは、Smaliが重要になります。これはDEXバイトコードの人間が読めるバージョンで、ソースコードをバイトコード命令に変換するアセンブリ言語のように機能します。Smaliとbaksmaliは、この文脈でのアセンブリおよび逆アセンブリツールを指します。
インテントは、Androidアプリがそのコンポーネント間または他のアプリと通信するための主要な手段です。これらのメッセージオブジェクトは、アプリ間やコンポーネント間でデータを運ぶこともでき、HTTP通信でのGET/POSTリクエストのように機能します。
したがって、インテントは基本的にコンポーネント間で渡されるメッセージです。インテントは特定のコンポーネントやアプリに向けられることができ、特定の受取人なしで送信されることもできます。 簡単に言えば、インテントは次のように使用できます:
アクティビティを開始するため、通常はアプリのユーザーインターフェースを開く
システムやアプリに変更を通知するためのブロードキャストとして
バックグラウンドサービスを開始、停止、通信するため
ContentProvidersを介してデータにアクセスするため
イベントを処理するためのコールバックとして
脆弱な場合、インテントはさまざまな攻撃を実行するために使用される可能性があります。
インテントフィルターは、アクティビティ、サービス、またはブロードキャストレシーバーが異なるタイプのインテントとどのように相互作用できるかを定義します。基本的に、これらのコンポーネントの能力を説明し、どのようなアクションを実行できるか、またはどのようなブロードキャストを処理できるかを示します。これらのフィルターを宣言する主な場所はAndroidManifest.xmlファイル内ですが、ブロードキャストレシーバーの場合は、コーディングすることも選択肢です。
インテントフィルターは、カテゴリ、アクション、およびデータフィルターで構成され、追加のメタデータを含めることができます。この設定により、コンポーネントは宣言された基準に一致する特定のインテントを処理できます。
Androidコンポーネント(アクティビティ/サービス/コンテンツプロバイダー/ブロードキャストレシーバー)の重要な側面は、その可視性または公開状態です。コンポーネントは、**exported
がtrue
の値である場合、またはマニフェスト内でインテントフィルターが宣言されている場合、公開と見なされ、他のアプリと相互作用できます。ただし、開発者はこれらのコンポーネントを明示的にプライベートに保つ方法があり、他のアプリと意図せず相互作用しないようにすることができます。これは、マニフェスト定義内でexported
属性をfalse
**に設定することで実現されます。
さらに、開発者は特定の権限を要求することで、これらのコンポーネントへのアクセスをさらに保護するオプションがあります。**permission
**属性を設定することで、指定された権限を持つアプリのみがコンポーネントにアクセスできるようにし、誰が相互作用できるかに対する追加のセキュリティと制御の層を追加します。
インテントは、インテントコンストラクタを使用してプログラム的に作成されます:
The Action of the previously declared intent is ACTION_SEND and the Extra is a mailto Uri (the Extra if the extra information the intent is expecting).
このインテントは、以下の例のようにマニフェスト内で宣言する必要があります:
インテントフィルターは、メッセージを受信するためにアクション、データ、およびカテゴリが一致する必要があります。
「インテント解決」プロセスは、どのアプリが各メッセージを受信するかを決定します。このプロセスは、intent-filter宣言で設定できる優先度属性を考慮し、優先度が高い方が選択されます。この優先度は-1000から1000の間で設定でき、アプリケーションはSYSTEM_HIGH_PRIORITY
値を使用できます。競合が発生した場合、「チョイザー」ウィンドウが表示され、ユーザーが決定できます。
明示的インテントは、ターゲットとするクラス名を指定します:
他のアプリケーションでは、以前に宣言されたインテントにアクセスするために次のように使用できます:
これにより、他のアプリケーションがあなたのアプリケーションの代理でアクションを実行することができます。Pending Intentを構築する際には、インテントと実行するアクションを指定する必要があります。もし宣言されたインテントが明示的でない場合(どのインテントが呼び出せるかを宣言していない場合)、悪意のあるアプリケーションが被害者アプリの代理で宣言されたアクションを実行する可能性があります。さらに、アクションが指定されていない場合、悪意のあるアプリは被害者の代理で任意のアクションを実行できるようになります。
前述のインテントとは異なり、1つのアプリだけが受信するのではなく、ブロードキャストインテントは複数のアプリで受信可能です。ただし、APIバージョン14以降は、メッセージを受信すべきアプリを指定することが可能です。Intent.setPackageを使用します。
また、ブロードキャストを送信する際に権限を指定することも可能です。受信アプリはその権限を持っている必要があります。
ブロードキャストには2種類があります:通常(非同期)と順序付き(同期)。順序は受信者要素内の設定された優先度に基づいています。各アプリはブロードキャストを処理、転送、または破棄できます。
Context
クラスの関数sendBroadcast(intent, receiverPermission)
を使用してブロードキャストを送信することが可能です。
また、**LocalBroadCastManager
のsendBroadcast
**関数を使用すると、メッセージがアプリを離れないことが保証されます。これを使用すると、受信者コンポーネントをエクスポートする必要すらありません。
この種のブロードキャストは送信された後も長期間アクセス可能です。 これらはAPIレベル21で非推奨となり、使用しないことが推奨されています。 これにより、任意のアプリケーションがデータを盗聴するだけでなく、変更することも可能です。
「sticky」という単語を含む関数(例:sendStickyBroadcast
やsendStickyBroadcastAsUser
)を見つけた場合は、影響を確認し、削除を試みてください。
Androidアプリケーションでは、ディープリンクを使用してURLを介して直接アクション(インテント)を開始します。これは、アクティビティ内で特定のURLスキームを宣言することによって行われます。Androidデバイスがこのスキームを持つURLにアクセスしようとすると、アプリケーション内の指定されたアクティビティが起動します。
スキームは**AndroidManifest.xml
**ファイルに宣言する必要があります:
前の例のスキームは examplescheme://
です(category BROWSABLE
も注意してください)
次に、データフィールドで host と path を指定できます:
ウェブからアクセスするには、次のようにリンクを設定することができます:
アプリで実行されるコードを見つけるために、ディープリンクによって呼び出されるアクティビティに移動し、**onNewIntent
**関数を検索します。
HTMLページを使用せずにディープリンクを呼び出す方法を学びましょう。
Androidインターフェース定義言語(AIDL)は、Androidアプリケーションにおけるクライアントとサービス間のプロセス間通信(IPC)を容易にするために設計されています。別のプロセスのメモリに直接アクセスすることはAndroidでは許可されていないため、AIDLはオブジェクトをオペレーティングシステムが理解できる形式にマーシャリングすることで、異なるプロセス間の通信を容易にします。
バウンドサービス: これらのサービスはIPCのためにAIDLを利用し、アクティビティやコンポーネントがサービスにバインドし、リクエストを行い、レスポンスを受け取ることを可能にします。サービスのクラス内のonBind
メソッドは、相互作用を開始するために重要であり、脆弱性を探すためのセキュリティレビューにおいて重要な領域です。
メッセンジャー: バウンドサービスとして機能するメッセンジャーは、onBind
メソッドを通じてデータを処理することに重点を置いたIPCを促進します。このメソッドを注意深く検査し、安全でないデータ処理や機密関数の実行がないか確認することが重要です。
バインダー: AIDLの抽象化によりバインダー・クラスの直接使用はあまり一般的ではありませんが、バインダーは異なるプロセスのメモリ空間間でデータ転送を促進するカーネルレベルのドライバーとして機能することを理解することは有益です。さらなる理解のために、リソースはhttps://www.youtube.com/watch?v=O-UHvFjxwZ8で入手可能です。
これには、アクティビティ、サービス、ブロードキャストレシーバー、プロバイダーが含まれます。
Androidアプリでは、アクティビティは画面のようなもので、アプリのユーザーインターフェースの異なる部分を表示します。アプリは多くのアクティビティを持つことができ、それぞれがユーザーにユニークな画面を提供します。
ランチャーアクティビティはアプリへの主要な入り口であり、アプリのアイコンをタップすると起動します。これは、特定のMAINおよびLAUNCHERインテントを持つアプリのマニフェストファイルで定義されています。
すべてのアプリがランチャーアクティビティを必要とするわけではなく、特にユーザーインターフェースのないバックグラウンドサービスのようなアプリは必要ありません。
アクティビティは、マニフェストで「exported」としてマークすることで、他のアプリやプロセスに利用可能にすることができます。この設定により、他のアプリがこのアクティビティを開始できるようになります:
しかし、別のアプリからアクティビティにアクセスすることが常にセキュリティリスクであるわけではありません。懸念は、機密データが不適切に共有される場合に生じ、情報漏洩につながる可能性があります。
アクティビティのライフサイクルはonCreateメソッドから始まり、UIを設定し、ユーザーとのインタラクションのためにアクティビティを準備します。
Android開発では、アプリはApplicationクラスのサブクラスを作成するオプションがありますが、必須ではありません。このようなサブクラスが定義されると、それはアプリ内で最初にインスタンス化されるクラスになります。**attachBaseContext
メソッドがこのサブクラスで実装されている場合、onCreate
**メソッドの前に実行されます。このセットアップにより、アプリケーションの残りの部分が開始される前に早期初期化が可能になります。
Services は バックグラウンドオペレーティブ であり、ユーザーインターフェースなしでタスクを実行することができます。これらのタスクは、ユーザーが異なるアプリケーションに切り替えても実行を続けることができるため、サービスは 長時間実行される操作 にとって重要です。
サービスは多用途であり、さまざまな方法で開始できますが、Intents がアプリケーションのエントリーポイントとしてサービスを起動する主な方法です。startService
メソッドを使用してサービスが開始されると、その onStart
メソッドが動作を開始し、stopService
メソッドが明示的に呼び出されるまで実行を続けます。あるいは、サービスの役割がアクティブなクライアント接続に依存している場合、bindService
メソッドを使用してクライアントをサービスにバインドし、データの受け渡しのために onBind
メソッドが呼び出されます。
サービスの興味深い応用には、バックグラウンドでの音楽再生やネットワークデータの取得が含まれ、ユーザーがアプリと対話することを妨げません。さらに、サービスは エクスポート を通じて同じデバイス上の他のプロセスにアクセス可能にすることができます。これはデフォルトの動作ではなく、Android Manifestファイルで明示的な設定が必要です:
Broadcast receivers は、メッセージングシステムにおけるリスナーとして機能し、複数のアプリケーションがシステムからの同じメッセージに応答できるようにします。アプリは Manifest を通じて、またはアプリのコード内で registerReceiver
API を使用して 2つの主要な方法 で レシーバーを登録 できます。Manifest では、ブロードキャストは権限でフィルタリングされ、動的に登録されたレシーバーは登録時に権限を指定することもできます。
Intent フィルター は、両方の登録方法で重要であり、どのブロードキャストがレシーバーをトリガーするかを決定します。一致するブロードキャストが送信されると、レシーバーの onReceive
メソッドが呼び出され、アプリが低バッテリーアラートに応じて動作を調整するなど、適切に反応できるようになります。
ブロードキャストは 非同期 であり、すべてのレシーバーに順序なしで到達することも、同期 であり、レシーバーが設定された優先順位に基づいてブロードキャストを受け取ることもできます。ただし、任意のアプリが自分自身を優先させてブロードキャストを傍受できる可能性があるため、潜在的なセキュリティリスクに注意することが重要です。
レシーバーの機能を理解するには、そのクラス内の onReceive
メソッドを探してください。このメソッドのコードは受信した Intent を操作でき、特に Ordered Broadcasts では、データの検証がレシーバーによって必要であることを強調しています。Ordered Broadcasts は Intent を変更または削除することができます。
Content Providers は、アプリ間で 構造化データを共有する ために不可欠であり、データセキュリティを確保するために 権限 を実装する重要性を強調しています。これにより、アプリはデータベース、ファイルシステム、またはウェブなど、さまざまなソースからデータにアクセスできます。特定の権限、例えば readPermission
と writePermission
は、アクセスを制御するために重要です。さらに、一時的なアクセスは、アプリのマニフェスト内の grantUriPermission
設定を通じて付与でき、path
、pathPrefix
、および pathPattern
などの属性を利用して詳細なアクセス制御を行います。
入力検証は、SQL インジェクションなどの脆弱性を防ぐために重要です。Content Providers は、データ操作とアプリケーション間の共有を促進する基本的な操作をサポートします:insert()
、update()
、delete()
、および query()
。
FileProvider は、ファイルを安全に共有することに特化した Content Provider です。これは、フォルダーへのアクセスを制御するための特定の属性を持ってアプリのマニフェストに定義され、android:exported
と android:resource
がフォルダー構成を指します。機密データを誤って公開しないように、ディレクトリを共有する際には注意が必要です。
FileProvider の例のマニフェスト宣言:
filepaths.xml
で共有フォルダーを指定する例:
For further information check:
WebViewsはAndroidアプリ内のミニウェブブラウザのようなもので、ウェブまたはローカルファイルからコンテンツを取得します。通常のブラウザと同様のリスクに直面しますが、特定の設定を通じてこれらのリスクを軽減する方法があります。
Androidは2つの主要なWebViewタイプを提供しています:
WebViewClientは基本的なHTMLには適していますが、JavaScriptアラート機能をサポートしていないため、XSS攻撃のテストに影響を与えます。
WebChromeClientは、フルChromeブラウザ体験に近い動作をします。
重要な点は、WebViewブラウザはデバイスのメインブラウザとクッキーを共有しないことです。
コンテンツを読み込むために、loadUrl
, loadData
, および loadDataWithBaseURL
などのメソッドが利用可能です。これらのURLまたはファイルが安全に使用できることを確認することが重要です。セキュリティ設定はWebSettings
クラスを通じて管理できます。たとえば、setJavaScriptEnabled(false)
でJavaScriptを無効にすることで、XSS攻撃を防ぐことができます。
JavaScriptの「ブリッジ」は、JavaオブジェクトがJavaScriptと相互作用することを可能にし、Android 4.2以降はセキュリティのためにメソッドに@JavascriptInterface
を付ける必要があります。
コンテンツアクセスを許可する(setAllowContentAccess(true)
)ことで、WebViewsはContent Providersにアクセスできますが、コンテンツURLが安全であることを確認しない限りリスクがあります。
ファイルアクセスを制御するために:
ファイルアクセスを無効にする(setAllowFileAccess(false)
)ことで、ファイルシステムへのアクセスが制限され、特定のアセットに対して例外が設けられ、非機密コンテンツのみに使用されることが保証されます。
デジタル署名はAndroidアプリに必須で、インストール前に正当に作成されたことを保証します。このプロセスでは、アプリの識別のために証明書が使用され、インストール時にデバイスのパッケージマネージャーによって検証される必要があります。アプリは自己署名または外部CAによって認証され、不正アクセスから保護され、デバイスへの配信中にアプリが改ざんされないことを保証します。
Android 4.2以降、Verify Appsという機能により、ユーザーはインストール前にアプリの安全性を確認できます。この検証プロセスは、潜在的に有害なアプリに対してユーザーに警告を発したり、特に悪意のあるアプリのインストールを防いだりすることで、ユーザーのセキュリティを強化します。
MDMソリューションは、デバイス管理APIを通じてモバイルデバイスの監視とセキュリティを提供します。これにより、モバイルデバイスを効果的に管理および保護するためにAndroidアプリのインストールが必要です。主な機能には、パスワードポリシーの強制、ストレージ暗号化の義務付け、およびリモートデータ消去の許可が含まれ、モバイルデバイスに対する包括的な制御とセキュリティを確保します。
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE) GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)