Android Applications Basics

ゼロからヒーローまでAWSハッキングを学ぶ htARTE(HackTricks AWS Red Team Expert)

HackTricksをサポートする他の方法:

Try Hard Security Group


Androidセキュリティモデル

2つのレイヤーがあります:

  • OS:インストールされたアプリケーションを互いに分離します。

  • アプリケーション自体:開発者が特定の機能を公開し、アプリケーションの機能を構成できます。

UID分離

各アプリケーションには特定のユーザーIDが割り当てられます。これはアプリのインストール時に行われ、アプリは自分のユーザーIDで所有されているファイルと共有ファイルにのみアクセスできます。したがって、アプリ自体、OSの特定のコンポーネント、およびルートユーザーだけがアプリのデータにアクセスできます。

UID共有

2つのアプリケーションを同じUIDを使用するように構成できます。これは情報を共有するのに役立ちますが、1つが侵害されると両方のアプリケーションのデータが侵害されます。このため、この動作は推奨されていません同じUIDを共有するには、アプリケーションはマニフェストで同じandroid:sharedUserId値を定義する必要があります。

サンドボックス

Androidアプリケーションサンドボックスを使用すると、各アプリケーション別のユーザーIDで別のプロセスとして実行できます。各プロセスには独自の仮想マシンがあり、アプリのコードは他のアプリから隔離されて実行されます。 Android 5.0(L)からはSELinuxが強制されています。基本的に、SELinuxはすべてのプロセスの相互作用を拒否し、それらの間で予想される相互作用のみを許可するポリシーを作成しました。

権限

アプリをインストールすると権限が求められます。アプリはAndroidManifest.xmlファイルの**uses-permission要素で構成された権限を要求しています。uses-permission要素は、name 属性内の要求された権限の名前を示します。maxSdkVersion属性もあり、指定されたバージョンよりも高いバージョンでは権限を要求しなくなります。 Androidアプリケーションは最初からすべての権限を要求する必要はなく、権限を動的に要求することもできますが、すべての権限はマニフェストで宣言**されている必要があります。

アプリが機能を公開すると、指定された権限を持つアプリにのみアクセスを制限できます。 権限要素には3つの属性があります:

  • 権限の名前

  • 権限グループをグループ化するpermission-group属性

  • 権限がどのように付与されるかを示すprotection-level。4つのタイプがあります:

    • Normal:アプリに既知の脅威がない場合に使用されます。ユーザーは承認を求められません

    • Dangerous:権限が要求されたアプリケーションに高度なアクセスを付与することを示します。ユーザーは承認を求められます

    • Signatureコンポーネントをエクスポートする証明書と同じ証明書で署名されたアプリのみが権限を付与されます。これは最も強力な保護のタイプです。

    • SignatureOrSystemコンポーネントをエクスポートする証明書と同じ証明書で署名されたアプリまたはシステムレベルのアクセスで実行されているアプリのみが権限を付与されます。

事前インストールされたアプリケーション

これらのアプリは一般的に**/system/appまたは/system/priv-appディレクトリにあり、一部は最適化**されています(classes.dexファイルが見つからない場合があります)。これらのアプリケーションは、rootとして実行されることが多いため、確認する価値があります。

  • AOSP(Androidオープンソースプロジェクト)ROMに含まれるもの

  • デバイスの製造元によって追加されたもの

  • 携帯電話プロバイダーによって追加されたもの(そこで購入した場合)

ルート化

物理的なAndroidデバイスでルートアクセスを取得するには、通常、デバイスとバージョンに特定の脆弱性を悪用する必要があります。 悪用が成功すると、通常はLinuxのsuバイナリがユーザーのPATH環境変数で指定された場所(たとえば/system/xbin)にコピーされます。

suバイナリが構成されると、他のAndroidアプリがsuバイナリとのインターフェイスを使用してrootアクセスのリクエストを処理するために使用されます(Google Playストアで利用可能なSuperuserSuperSUなど)。

ルート化プロセスは非常に危険であり、デバイスに重大な損害を与える可能性があります

ROM

カスタムファームウェアをインストールしてOSを置き換えることができます。これにより、古いデバイスの有用性を拡張したり、ソフトウェアの制限をバイパスしたり、最新のAndroidコードにアクセスしたりすることができます。 OmniROMLineageOSは、最も人気のあるファームウェアの2つです。

デバイスをルート化する必要が常にあるわけではないことに注意してください。一部のメーカーは、ブートローダーのアンロックを十分に文書化された安全な方法で許可しています。

影響

デバイスがルート化されると、任意のアプリがrootアクセスを要求できます。悪意のあるアプリがそれを取得した場合、ほとんどすべてにアクセスでき、電話を破損させることができます。

Androidアプリケーションの基礎

  • Androidアプリケーションの形式は_APKファイル形式_と呼ばれます。実質的にはZIPファイルです(ファイル拡張子を.zipに変更することで、内容を抽出して表示できます)。

  • APKの内容(完全ではありません)

    • AndroidManifest.xml

    • resources.arsc/strings.xml

    • resources.arsc:バイナリXMLなど、事前にコンパイルされたリソースが含まれています。

    • res/xml/files_paths.xml

    • META-INF/

      • 証明書がここにあります!

    • classes.dex

      • デフォルトでアプリが実行する、コンパイルされたJava(またはKotlin)コードを表すDalvikバイトコードが含まれています。

    • lib/

      • CPUアーキテクチャごとにサブディレクトリに分かれたネイティブライブラリが格納されています。

        • armeabi:ARMベースのプロセッサ用のコード

        • armeabi-v7a:ARMv7およびそれ以上のプロセッサ用のコード

        • x86:X86プロセッサ用のコード

        • mips:MIPSプロセッサ用のコードのみ

    • assets/

      • アプリが必要とするさまざまなファイルを格納し、追加のネイティブライブラリやDEXファイルを含むことがあります。マルウェアの作者が追加のコードを隠すために使用することがあります。

    • res/

      • resources.arscにコンパイルされていないリソースが含まれています

Dalvik & Smali

Android開発では、JavaまたはKotlinがアプリを作成するために使用されます。デスクトップアプリケーションとは異なり、AndroidはこのコードをDalvik Executable (DEX) bytecodeにコンパイルします。以前はDalvik仮想マシンがこのバイトコードを処理していましたが、新しいAndroidバージョンではAndroid Runtime (ART)が引き継いでいます。

逆コンパイルには、Smaliが重要です。これはDEXバイトコードの人間が読めるバージョンであり、ソースコードをバイトコード命令に変換することでアセンブリ言語のように機能します。この文脈では、Smaliとbaksmaliはアセンブリと逆アセンブリのツールを指します。

インテント

インテントは、Androidアプリがコンポーネント間や他のアプリと通信する主要な手段です。これらのメッセージオブジェクトは、アプリ間やコンポーネント間でデータをやり取りすることもでき、HTTP通信でのGET/POSTリクエストのように機能します。

つまり、インテントは基本的にコンポーネント間で渡されるメッセージです。インテントは特定のコンポーネントやアプリに向けられることができ、または特定の受信者なしに送信することもできます。 簡単に言うと、インテントは以下のように使用できます:

  • 通常はアプリのユーザーインターフェースを開くためにActivityを開始するため

  • システムやアプリに変更を通知するためのブロードキャストとして

  • バックグラウンドサービスの開始、停止、および通信のため

  • ContentProvidersを介してデータにアクセスするため

  • イベントを処理するためのコールバックとして

脆弱性がある場合、インテントはさまざまな攻撃に使用される可能性があります。

インテントフィルタ

インテントフィルタは、アクティビティ、サービス、またはブロードキャストレシーバが異なるタイプのインテントとやり取りする方法を定義します。基本的に、これらのコンポーネントの機能を説明し、実行できるアクションや処理できるブロードキャストの種類などを示します。これらのフィルタを宣言する主な場所はAndroidManifest.xmlファイルですが、ブロードキャストレシーバの場合はコーディングすることもできます。

インテントフィルタは、カテゴリ、アクション、およびデータフィルタで構成され、追加のメタデータを含めることもできます。この設定により、特定の基準に一致するインテントを処理できるコンポーネントが可能になります。

Androidコンポーネント(アクティビティ/サービス/コンテンツプロバイダ/ブロードキャストレシーバ)の重要な側面は、その可視性または公開状態です。コンポーネントは、マニフェストで**exported属性をtrueに設定するか、そのコンポーネントのためにインテントフィルタが宣言されている場合にのみ、他のアプリとやり取りできると見なされます。ただし、開発者はこれらのコンポーネントを意図せず他のアプリとやり取りさせないように明示的に非公開に保つ方法があります。これは、マニフェスト定義でexported属性をfalse**に設定することで実現できます。

さらに、開発者はこれらのコンポーネントへのアクセスをさらに保護するために特定の権限を要求するオプションがあります。**permission**属性を設定して、指定された権限を持つアプリのみがコンポーネントにアクセスできるように強制することで、セキュリティと誰がそれとやり取りできるかを制御する追加のセキュリティレイヤーを追加できます。

<activity android:name=".MyActivity" android:exported="false">
<!-- Intent filters go here -->
</activity>

暗黙的インテント

インテントは、Intentコンストラクタを使用してプログラムで作成されます:

Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));

アクションは以前に宣言されたインテントのACTION_SENDであり、Extraはmailto Uriです(Extraはインテントが期待している追加情報です)。

このインテントは、次の例のようにマニフェスト内で宣言する必要があります:

<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

An intent-filter needs to match the action, data and category to receive a message.

The "Intent resolution" process determine which app should receive each message. This process considers the priority attribute, which can be set in the intent-filter declaration, and the one with the higher priority will be selected. This priority can be set between -1000 and 1000 and applications can use the SYSTEM_HIGH_PRIORITY value. If a conflict arises, a "choser" Window appears so the user can decide.

Explicit Intents

An explicit intent specifies the class name it's targeting:

Intent downloadIntent = new (this, DownloadService.class):

他のアプリケーションで以前に宣言されたインテントにアクセスするためには、次のようにします:

Intent intent = new Intent();
intent.setClassName("com.other.app", "com.other.app.ServiceName");
context.startService(intent);

ペンディングインテント

これにより、他のアプリケーションがあなたのアプリケーションの代わりにアクションを実行できます。ペンディングインテントを構築する際は、インテントと実行するアクションを指定する必要があります宣言されたインテントが明示的でない場合(どのインテントが呼び出せるかを宣言していない場合)、悪意のあるアプリケーションが被害者アプリの代わりに宣言されたアクションを実行できます。さらに、アクションが指定されていない場合、悪意のあるアプリは被害者の代わりに任意のアクションを実行できます。

ブロードキャストインテント

以前のインテントとは異なり、ブロードキャストインテントは複数のアプリに受信されることができます。ただし、APIバージョン14以降では、Intent.set Packageを使用してメッセージを受信するアプリを指定することが可能です。

また、ブロードキャストを送信する際にパーミッションを指定することも可能です。受信アプリはそのパーミッションを持っている必要があります。

ブロードキャストには通常(非同期)と順序付け(同期)の2つのタイプがあります。順序レシーバ内で構成された優先順位に基づいています。各アプリはブロードキャストを処理、中継、または破棄することができます。

ContextクラスからsendBroadcast(intent, receiverPermission)関数を使用してブロードキャストを送信することが可能です。 また、**LocalBroadCastManagerからsendBroadcast**関数を使用すると、メッセージがアプリを離れることはなくなります。これを使用すると、レシーバコンポーネントをエクスポートする必要すらありません。

スティッキーブロードキャスト

この種のブロードキャストは、送信後も長い時間アクセスできます。 これらはAPIレベル21で非推奨となり、使用しないことが推奨されています。 これにより、任意のアプリケーションがデータを嗅ぎ取るだけでなく、変更することも可能です。

**sendStickyBroadcastsendStickyBroadcastAsUser**など、"sticky"という単語を含む関数を見つけた場合は、影響を確認して削除を試みてください

ディープリンク / URLスキーム

Androidアプリケーションでは、ディープリンクが使用され、URLを介して直接アクション(インテント)を開始します。これは、アクティビティ内で特定のURLスキームを宣言することによって行われます。Androidデバイスがこのスキームを持つURLにアクセスしようとすると、アプリケーション内の指定されたアクティビティが起動されます。

スキームは**AndroidManifest.xml**ファイルに宣言する必要があります。

[...]
<activity android:name=".MyActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="examplescheme" />
</intent-filter>
[...]

前の例からのスキームは exampleapp://category BROWSABLE も参照)

次に、データフィールドで ホストパス を指定できます:

<data android:scheme="examplescheme"
android:host="example"
/>

Webからアクセスするには、次のようにリンクを設定することができます:

<a href="examplescheme://example/something">click here</a>
<a href="examplescheme://example/javascript://%250dalert(1)">click here</a>

アプリで実行されるコードを見つけるには、ディープリンクで呼び出されるアクティビティに移動し、onNewIntent 関数を検索します。

HTML ページを使用せずにディープリンクを呼び出す方法を学びます。

AIDL - Android Interface Definition Language

Android Interface Definition Language (AIDL) は、Android アプリケーション内のクライアントとサービス間のコミュニケーションを容易にするために設計されています。別のプロセスのメモリに直接アクセスすることは Android では許可されていないため、AIDL はオブジェクトをオペレーティングシステムが理解する形式に変換することで、異なるプロセス間の通信を容易にします。

主要な概念

  • バウンド サービス: これらのサービスは IPC に AIDL を使用し、アクティビティやコンポーネントがサービスにバインドしてリクエストを行い、レスポンスを受け取ることを可能にします。サービスのクラス内の onBind メソッドは、相互作用を開始するために重要であり、脆弱性を探すためのセキュリティレビューの重要な領域としてマークされています。

  • Messenger: バウンド サービスとして機能する Messenger は、onBind メソッドを介してデータの処理に焦点を当てた IPC を可能にします。このメソッドを注意深く検査し、安全でないデータ処理や機密関数の実行がないかを確認することが重要です。

  • Binder: AIDL の抽象化により Binder クラスの直接的な使用は一般的ではありませんが、Binder は異なるプロセスのメモリ空間間でのデータ転送を可能にするカーネルレベルのドライバとして機能します。さらなる理解のために、リソースがこちらで利用可能です。

コンポーネント

これには、アクティビティ、サービス、ブロードキャスト レシーバー、プロバイダーが含まれます。

ランチャーアクティビティとその他のアクティビティ

Android アプリでは、アクティビティは画面のようなもので、アプリのユーザーインターフェースの異なる部分を表示します。アプリには多くのアクティビティがあり、それぞれがユーザーに一意の画面を表示します。

ランチャーアクティビティはアプリへのメインゲートウェイであり、アプリのアイコンをタップすると起動されます。これはアプリのマニフェストファイルで特定の MAIN および LAUNCHER インテントで定義されています。

<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Android Applications Basics

いくつかのアプリには、バックグラウンドサービスのようにユーザーインターフェースを持たないものを含め、ランチャーアクティビティが必要ないものもあります。

アクティビティは、マニフェストで「exported」とマークすることで、他のアプリやプロセスで利用可能にすることができます。この設定により、他のアプリがこのアクティビティを起動できるようになります。

<service android:name=".ExampleExportedService" android:exported="true"/>

しかし、別のアプリからアクティビティにアクセスすること自体が常にセキュリティリスクというわけではありません。懸念されるのは、機密データが適切に共有されていない場合であり、これは情報漏洩につながる可能性があります。

アクティビティのライフサイクルは、onCreate メソッドで始まり、UIの設定とアクティビティのユーザーとのやり取りの準備を行います。

アプリケーションのサブクラス

Android開発では、アプリはApplicationクラスのサブクラスを作成するオプションがありますが、これは必須ではありません。このようなサブクラスが定義されている場合、それがアプリ内で最初にインスタンス化されるクラスとなります。このサブクラスで実装されている場合、attachBaseContext メソッドは onCreate メソッドの前に実行されます。このセットアップにより、アプリケーションの残りの部分が開始される前に初期化を行うことができます。

public class MyApp extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
// Initialization code here
}

@Override
public void onCreate() {
super.onCreate();
// More initialization code
}
}

サービス

サービスはユーザーインターフェースなしでタスクを実行できるバックグラウンドオペレータです。これらのタスクは、ユーザーが異なるアプリケーションに切り替えても継続して実行されるため、長時間実行される操作にはサービスが不可欠です。

サービスは多目的であり、さまざまな方法で開始できます。インテントは、サービスを起動するための主要な方法であり、アプリケーションのエントリーポイントとして機能します。サービスをstartServiceメソッドを使用して開始すると、そのonStartメソッドが実行され、stopServiceメソッドが明示的に呼び出されるまで実行を継続します。また、サービスの役割がアクティブなクライアント接続に依存する場合、bindServiceメソッドを使用してクライアントをサービスにバインドし、データの受け渡しにonBindメソッドを使用します。

サービスの興味深い応用例には、アプリとのやり取りを妨げることなく、バックグラウンドで音楽を再生したり、ネットワークデータを取得したりすることが挙げられます。さらに、サービスはエクスポートを介して同じデバイス上の他のプロセスからアクセス可能にすることができます。これはデフォルトの動作ではなく、Android Manifestファイルで明示的に構成する必要があります。

<service android:name=".ExampleExportedService" android:exported="true"/>

ブロードキャストレシーバ

ブロードキャストレシーバは、メッセージングシステムにおけるリスナーとして機能し、複数のアプリケーションがシステムからの同じメッセージに応答できるようにします。アプリは、マニフェストを介してまたはアプリのコード内で registerReceiver API を使用して、2つの主要な方法レシーバを登録できます。マニフェストでは、ブロードキャストは権限でフィルタリングされますが、動的に登録されたレシーバは登録時に権限を指定することもできます。

インテントフィルタは、登録方法に関係なく重要であり、どのブロードキャストがレシーバをトリガーするかを決定します。一致するブロードキャストが送信されると、レシーバの onReceive メソッドが呼び出され、アプリは適切に反応することができます。たとえば、低バッテリーアラートに応じて動作を調整するなどです。

ブロードキャストは、非同期であり、順不同ですべてのレシーバに到達するか、同期であり、レシーバが優先順位に基づいてブロードキャストを受け取るかのいずれかです。ただし、どのアプリも自分自身を優先してブロードキャストを傍受できる可能性があるため、潜在的なセキュリティリスクに注意することが重要です。

レシーバの機能を理解するには、そのクラス内の onReceive メソッドを探します。このメソッドのコードは受信したインテントを操作でき、特に 順序付けられたブロードキャストでは、インテントを変更したり破棄したりする必要があるため、レシーバによるデータの検証が重要です。

コンテンツプロバイダ

コンテンツプロバイダは、アプリケーション間で 構造化されたデータを共有するために不可欠であり、データセキュリティを確保するために 権限の実装の重要性を強調しています。これにより、アプリはデータベース、ファイルシステム、またはウェブなど、さまざまなソースからデータにアクセスできます。readPermission および writePermission のような特定の権限は、アクセスを制御するために重要です。さらに、一時的なアクセスは、アプリのマニフェストで grantUriPermission 設定を介して付与でき、pathpathPrefixpathPattern などの属性を活用して詳細なアクセス制御を行います。

脆弱性(SQLインジェクションなど)を防ぐために、入力検証は極めて重要です。コンテンツプロバイダは、insert()update()delete()query() などの基本操作をサポートし、データの操作とアプリケーション間での共有を容易にします。

FileProvider は、ファイルを安全に共有することに焦点を当てた特殊なコンテンツプロバイダです。フォルダへのアクセスを制御するための特定の属性でアプリのマニフェストで定義され、android:exported および android:resource がフォルダ構成を指すようになっています。機密データが誤って公開されるのを避けるために、ディレクトリを共有する際には注意が必要です。

FileProvider の例示的なマニフェスト宣言:

<provider android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>

そして、filepaths.xml で共有フォルダを指定する例:

<paths>
<files-path path="images/" name="myimages" />
</paths>

For further information check:

WebViews

WebViews are like mini web browsers inside Android apps, pulling content either from the web or from local files. They face similar risks as regular browsers, yet there are ways to reduce these risks through specific settings.

Android offers two main WebView types:

  • WebViewClient is great for basic HTML but doesn't support the JavaScript alert function, affecting how XSS attacks can be tested.

  • WebChromeClient acts more like the full Chrome browser experience.

A key point is that WebView browsers do not share cookies with the device's main browser.

For loading content, methods such as loadUrl, loadData, and loadDataWithBaseURL are available. It's crucial to ensure these URLs or files are safe to use. Security settings can be managed via the WebSettings class. For instance, disabling JavaScript with setJavaScriptEnabled(false) can prevent XSS attacks.

The JavaScript "Bridge" lets Java objects interact with JavaScript, requiring methods to be marked with @JavascriptInterface for security from Android 4.2 onwards.

Allowing content access (setAllowContentAccess(true)) lets WebViews reach Content Providers, which could be a risk unless the content URLs are verified as secure.

To control file access:

  • Disabling file access (setAllowFileAccess(false)) limits access to the filesystem, with exceptions for certain assets, ensuring they're only used for non-sensitive content.

Other App Components and Mobile Device Management

Digital Signing of Applications

  • Digital signing is a must for Android apps, ensuring they're authentically authored before installation. This process uses a certificate for app identification and must be verified by the device's package manager upon installation. Apps can be self-signed or certified by an external CA, safeguarding against unauthorized access and ensuring the app remains untampered during its delivery to the device.

App Verification for Enhanced Security

  • Starting from Android 4.2, a feature called Verify Apps allows users to have apps checked for safety before installation. This verification process can warn users against potentially harmful apps, or even prevent the installation of particularly malicious ones, enhancing user security.

Mobile Device Management (MDM)

  • MDM solutions provide oversight and security for mobile devices through Device Administration API. They necessitate the installation of an Android app to manage and secure mobile devices effectively. Key functions include enforcing password policies, mandating storage encryption, and permitting remote data wipe, ensuring comprehensive control and security over mobile devices.

// Example of enforcing a password policy with MDM
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName adminComponent = new ComponentName(context, AdminReceiver.class);

if (dpm.isAdminActive(adminComponent)) {
// Set minimum password length
dpm.setPasswordMinimumLength(adminComponent, 8);
}

Try Hard Security Group

htARTE(HackTricks AWS Red Team Expert)を使用して、ゼロからヒーローまでAWSハッキングを学ぶ

HackTricksをサポートする他の方法:

Last updated