Android Pentest: Deep Link Exploitation
Introduction to Deep Links
In many scenarios an application needs to deal with web based URLs in order to authenticate users using Oauth login, create and transport session IDs and various other test cases. In such scenarios, developers configure deep links, aka, custom URL schemas that tell the application to open a specific type of URL in the app directly. This only works in Android v6.0 and above. The intent filter to accept URIs that have example.com as the host and http:// as URL scheme is defined in an Android Manifest file as follows:
<intent-filter android:label="@string/filter_view_http_gizmos"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <!-- Accepts URIs that begin with "http://www.example.com/gizmos” --> <data android:scheme="http" android:host="www.example.com" android:pathPrefix="/gizmos" /> <!-- note that the leading "/" is required for pathPrefix--> </intent-filter>
Pay focus to data android:scheme=”http” and android:host=”<domain>”
Similarly, the intent filter to define a custom scheme (eg: to open URLs that open with example://gizmos.com) is as follows:
<intent-filter android:label="@string/filter_view_example_gizmos"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <!-- Accepts URIs that begin with "example://gizmos” --> <data android:scheme="example" android:host="gizmos" /> </intent-filter>
In this article, we’ll be looking at how an attacker can exploit poor implementation of URL schemas to conduct various attacks.
Where can it go wrong?
Oftentimes developers use deep links to pass sensitive data from a web URL to an application like usernames, passwords, and session Ids. An attacker can create an application that fires off an intent and exploit this custom URL scheme (deep link) to perform attacks like:
- Sensitive data exposure
- Session hijacking
- Account takeovers
- Open redirect
- XSS using WebView implementation of a Deep Link
For example, a poor implementation would be: example://api.example.com/v1/users/sessionId=12345
Here, One can change the session ID to 12346 or 12347, and in the application, that particular user’s session would open as to which that session ID corresponds. This Url could be obtained while traffic analysis and a rogue application/HTML phishing page could trigger that activity and perform account takeover.
Let’s see a basic real-time demonstration of exploiting deep links using drozer.
I have coded this small application that I initially built to demonstrate android hooking and added a deep link scheme to call this activity. To download this app follow here. Ideally, you must decompile this app and figure out what the URL scheme is from the Manifest file. Here is how the application looks like. Read the instructions given in the screenshot.
Now, you’ll notice that you won’t be able to open the activity directly using the button below. Hence, we’ll have to exploit deeplink to launch the activity.
The first step here would be to view the manifest file and check which URL scheme is being used. For that I run the following drozer command:
run app.package.manifest in.harshitrajpal.deeplinkexample
Note here, the <data scheme=””> has a value “noob” so maybe we can fire an intent with a data URL containing a URL of this scheme so that it launches this activity?
Note: It is to be noted that any activity that is declared under an intent filter is by default exported and hence can be called via a rogue app that fires off that particular intent. Developers must also be very mindful of the fact that mere URL authentication is not sufficient due to this fact.
To view exported activities:
run app.activity.info -a in.harshitrajpal.deeplinkexample
We see DeepLinkActivity being used here.
We can launch this activity using our DeepLink exploitation technique. On exploring its source code we see that it is accepting data URL with an intent to perform some action. This action could be authentication, webviews, etc. But for the purpose of demonstration, I have coded a simple 10+50 sum calculator (that we saw in the android hooking article)
First, let’s see what happens when we open a generic URL:
run app.activity.start --action android.intent.action.VIEW --data-url http://google.com
As visible, the intent is fired up in a browser.
Now, let’s form another query in drozer that’ll fire up DeepLinkActivity.java in our application using deeplink.
run app.activity.start --action android.intent.action.VIEW –data-uri noob://harshit.com/auth=sum
This is a random URL that doesn’t mean anything and doesn’t perform any action. I’ve just demonstrated that an authentication action can be performed using deep links like this.
As you can see, this URL has fired up the application class that I had created. This is because Android Manifest has directed the android system to redirect any URL that begins with the scheme “noob://” to open up with my application DeepLinkExample
Now, an attacker could host a phishing page with “a href” tag that contains a URL of this scheme, sends this page to a victim via social engineering, he could steal his session ID using this. In the screenshot below you can see one such URL that I’ve crafted to steal session key from the DeepLinkExample app using noob:// scheme.
<html> <body> <a href="noob://hello.com/yolo?=auth&session=exampleKey">click here to exploit</a> </body> </html>
Let’s host this using our python server
python3 -m http.server 80
Let’s open this HTML link on our mobile browser. We see something like this:
On clicking this link our application opens successfully!
Now, let’s see another intentionally vulnerable application called InjuredAndroid created by b3nac (Follow here). This application also has a vulnerable Deep Link activity. Since it is in intent-filter it is exported by default. Hence, we can launch this activity directly using the drozer.
run app.activity.info -a b3nac.injuredandroid
We see DeepLinkActivity is exported. We try to call it using drozer
run app.activity.start --component b3nac.injuredandroid b3nac.injuredandroid.DeepLinkActivity
We now, take a look at its manifest file to discover the scheme that’s being used.
run app.package.maifest in.harshitrajpal.deeplinkexample
Here, we see the flag11 scheme being used in DeepLinkActivity.
Now, to open this activity using this custom URL scheme, we can do something like:
run app.activity.start --action android.intent.action.VIEW --data-uri flag11://abc.com
Alternatively, it can also be exploited using an HTML phishing page and social engineering attack:
<html> <body> <a href="flag11://hello.com/yolo?=auth&session=exampleKey">click here to exploit</a> </body> </html>
python3 -m http.server 80
Now, clicking on this link in a browser, we see that DeepLinkActivity successfully opens up!
How to avoid misuse of insecure deep link implementation
The measures are as follows: –
- Since deep links are configured within the app, a developer could have a secret value communicated to the app by a remote back end server over a secure transmission protocol.
- Verification of Deep Links as App Links can be done by setting android:autoVerify=”true” in the manifest file
- One can include a JSON file with the name assetlinks.json in your web server that is described by the web URL intent filter
In the article, we learned how to exploit deep links to eventually cause critical damage. In a well-built application, Deep Link could just be the perfect butterfly effect that leads to many critical vulnerabilities. In the references below, you’ll find some real-time bug bounty reports that include deep link abuse. Thanks for reading.
Author: Harshit Rajpal is an InfoSec researcher and left and right brain thinker. Contact here