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.
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:
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: –
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.
https://hackerone.com/reports/401793
https://hackerone.com/reports/583987
https://hackerone.com/reports/855618
https://www.nowsecure.com/blog/2019/04/05/how-to-guard-against-mobile-app-deep-link-abuse/
Author: Harshit Rajpal is an InfoSec researcher and left and right brain thinker. Contact here