Android Task Hijacking

Reading time: 12 minutes

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

タスク、バックスタックとフォアグラウンドアクティビティ

Androidにおいて、タスクはユーザーが特定の作業を完了するために対話するアクティビティのセットであり、バックスタック内に整理されています。このスタックはアクティビティが開かれた順に並べられ、最も最近のアクティビティが最上部に表示され、これがフォアグラウンドアクティビティとなります。どの瞬間でも、このアクティビティだけが画面に表示され、フォアグラウンドタスクの一部となります。

アクティビティの遷移の簡単な説明は以下の通りです:

  • アクティビティ 1 はフォアグラウンドの唯一のアクティビティとして開始されます。
  • アクティビティ 2 を起動すると、アクティビティ 1 はバックスタックに押し出され、アクティビティ 2 がフォアグラウンドに表示されます。
  • アクティビティ 3 を開始すると、アクティビティ 1アクティビティ 2 はスタックのさらに後ろに移動し、アクティビティ 3 が前面に出ます。
  • アクティビティ 3 を閉じると、アクティビティ 2 が再びフォアグラウンドに戻り、Androidの効率的なタスクナビゲーションメカニズムを示します。

https://developer.android.com/images/fundamentals/diagram_backstack.png


タスクアフィニティ攻撃

taskAffinityは、Activity属したいタスクをAndroidに伝えます。2つのアクティビティが同じアフィニティを共有している場合、Androidは異なるAPKから来たものであっても、それらを同じバックスタック内にマージすることが許可されます

攻撃者がそのスタックのルートに悪意のあるアクティビティを配置できれば、被害者が正当なアプリケーションを開くたびに、悪意のあるUIがユーザーの最初に表示されます - フィッシングや悪用の権限要求に最適です。

攻撃面は多くの開発者が考えるよりも広範囲で、すべてのアクティビティは自動的にアプリケーションパッケージ名と等しいアフィニティを継承します(開発者がandroid:taskAffinity=""を設定しない限り)。したがって、何もしないことは、Android 11以前のバージョンでタスクハイジャックに対してアプリを開いたままにします。

クラシックな「singleTask / StrandHogg」シナリオ

  1. 攻撃者は次のようにアクティビティを宣言します:
xml
<activity android:name=".EvilActivity"
android:exported="true"
android:taskAffinity="com.victim.package"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
  1. 悪意のあるアプリが一度起動され、タスク(偽のアフィニティを持つ)が最近のタスクに存在します。
  2. ユーザーが後で本物のアプリケーションを開くと、Androidはすでにルートアフィニティがパッケージと一致するタスクがあることを見つけ、そのタスクをフォアグラウンドに持ってきます。
  3. 攻撃者のUIが最初に表示されます。

デフォルトアフィニティ(singleTaskなし)バリアント - コーラーIDケーススタディ

**コーラーID(caller.id.phone.number.block)**アプリケーションで報告された脆弱性は、攻撃がデフォルトのstandard起動モードに対しても機能することを示しています:

  1. 攻撃者アプリが偽のルートアクティビティを作成し、すぐに自分自身を隠します:
kotlin
class HackActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
moveTaskToBack(true)   // タスクを最近のものに保ちながら視界から外す
}
}
  1. マニフェストは被害者のパッケージをtaskAffinityにコピーするだけで済みます:
xml
<activity android:name=".HackActivity"
android:exported="true"
android:taskAffinity="com.caller.id.phone.number.block" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
  1. ユーザーが悪意のあるアプリを一度インストールして開くと、被害者パッケージと等しいアフィニティを持つタスクが存在します(ただしバックグラウンドにあります)。
  2. 本物のコーラーIDアプリケーションが起動されると、Androidはそのタスクを再利用し、HackActivityをフォアグラウンドに持ってきます → フィッシングウィンドウ/権限の悪用。

注:**Android 11(API 30)**以降、システムはデフォルトで同じUIDの一部でない2つのパッケージを同じタスクに配置しないため、この特定のバリアントを軽減します。古いバージョンは依然として脆弱です。


StrandHogg 2.0 (CVE-2020-0096) – リフレクションベースのタスクハイジャック

Googleの2020年5月のセキュリティ速報は、StrandHogg 2.0と呼ばれるより高度なバリアントを修正しました。このエクスプロイトは**taskAffinityに全く依存せず**、代わりにリフレクションを使用して、すべての実行中のタスクの最上部に攻撃者のアクティビティを動的に挿入し、Android 11によって導入された「共有UID」制限を完全に回避します。

重要なポイント:

  • ゼロ権限の悪意のあるアプリは、一度開かれると、実行中のタスクを反復処理し、隠されたAPIを呼び出して自分のアクティビティを任意のタスクに再親子化できます。
  • アクティビティが実行時に挿入されるため、launchModeや静的マニフェスト分析では事前に攻撃を検出できません。
  • Android 8.0/8.1/9(2020年5月SPL)にチェックをバックポートすることで修正されました。Android 10以降は影響を受けません。

パッチが適用されていないデバイスでの検出は、adb shell dumpsys activity activitiesを使用して、タスクのアフィニティと異なるパッケージ名を持つ疑わしいアクティビティを監視することで行えます。

レガシーデバイスの軽減策は、クラシックなタスクハイジャックと同じで、さらに実行時検証(例:ActivityManager#getRunningTasksを呼び出し、自分のパッケージ名を検証する)を行います。


検出と悪用チェックリスト

  1. 静的レビュー – ターゲットAPKからAndroidManifest.xmlを引き出し、各<activity>(またはグローバル<application>要素)がandroid:taskAffinity=""(空)またはカスタマイズされた値を含んでいることを確認します。ツールは次の通りです:
bash
# apkanalyzerを使用(Android SDK)
apkanalyzer manifest print app.apk | grep -i taskaffinity

# AXMLPrinter2を使用
java -jar AXMLPrinter2.jar AndroidManifest.xml | grep taskAffinity
  1. 動的レビュー – デバイス上でターゲットアプリを開き、タスクをリストします:
bash
adb shell dumpsys activity activities | grep -A3 "TASK" | grep -E "Root|affinity"

ルートアフィニティが被害者パッケージと等しいが、最上部のアクティビティが異なるパッケージに属しているタスクは赤信号です。 3. 上記のように悪意のあるアプリを作成するか、**Drozer**を使用します:

bash
drozer console connect
run app.activity.start --component com.victim/.MainActivity --action android.intent.action.MAIN
run app.activity.info com.victim

軽減策

開発者は以下を行うべきです:

  • <application>レベルでandroid:taskAffinity=""を明示的に設定する(推奨)または各アクティビティにユニークでプライベートなアフィニティを与える。
  • 非常に敏感な画面に対しては、上記をandroid:launchMode="singleInstance"または現代のsetLaunchMode保護と組み合わせる。
  • アプリのtargetSdkVersionをアップグレードし、タスクがデフォルトでパッケージ間で共有されないAndroid 11の動作変更を強制する。
  • Android 12(API 31)以上をターゲットにして、必須のandroid:exported属性が開発者にすべての外部到達可能なコンポーネントを監査させる。
  • 実行時の自己防御を考慮する:定期的にActivityTaskManagerをクエリして、最上部のアクティビティのパッケージが自分のものであることを確認する。

関連するUIハイジャック技術

タスクハイジャックは、しばしばタップジャッキング(オーバーレイベースのUI欺瞞)と組み合わされるか、置き換えられます。2025年のTapTrap研究は、完全に透明なアニメーション駆動アクティビティがAndroid 12–14で導入されたオーバーレイタッチ制限を回避し、ユーザーを危険な権限を付与するように騙すことができることを示しました。TapTrapは厳密にはタスクハイジャックではありませんが、最終的な目標(フィッシングクリック)は同じであるため、現代の評価では両方の攻撃面をチェックする必要があります。


参考文献

tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする