Recently, I have been studying Android penetration testing, and I came across a new topic called ‘Deep Links’. Since it is a new topic to me, I decided to share the knowledge I gained from hours of searching, may it save someone else time.
Introduction to Deep Links
If you come from a web background like I did, you can think about deep links as hyperlinks that can take users directly to a specific page or content within a mobile app.
It’s very much like regular links but, instead of opening a web page, deep links are designed to navigate users to a precise location or activities within an app.
The idea is to enhance user experience and engagement in mobile apps.
Deep links types
There are 3 types of deep links and they are summarized in this picture
As you can see, it is like a hierarchy, each type is a special case from the previous type. We will explain each one briefly.
- Deep links
It handles URIs in the form of scheme://authority/path
the scheme can be a standard scheme like http,https
or a custom one like app://
the authority should have a domain structure to make ownership of the link clear. Finally /path
which is used to send the user to a particular activity based on your app logic.
2. Web links
From its name, this is the URL that we already know, most web links are considered deep links. It handles URIs with the http/https
schemes only.
3. Android app links
Android App Links is a special type of deep link that allows website URLs to immediately open the corresponding content in an app. Must have the autoVerify
attribute set to true.
Deep links setup
Deep links are set up by adding intent filters. Several apps are able to handle the same deep links. In this case, users might not go directly to a particular app and must select an app.
The following XML snippet shows an example of an intent filter in a manifest for deep linking, where the app://exampleApp
URI is resolved to the MainActivity
:
<activity android:name="MainActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Here is the declaration of the scheme, host and path -->
<data android:scheme="app"
android:host="exampleApp" />
</intent-filter>
</activity>
Exploitation
Now we know what are deep links, it is time to try and exploit them and see their impact. I will show a demo of 2 intentionally vulnerable apps.
InsecureShop
Insecureshop is an intentionally vulnerable Android application you can download it from here.
Our goal is simple, find the deep link and exploit it. In order to find the deep link we need to decompile the app with tools like Jadx.
After that, open the AndroidManifest.xml
and look for andorid:scheme
As you can see, we have one hit. The WebViewActivity defines an intent filter that uses the deep link insecureshop://com.insecureshop
So, let us go to that activity and see how the deep link is handled.
In this code snippet, the developer defines a WebView component with some settings set to true. We are interested in 2 of them, setJavaScriptEnapled
this enables us to run javascript on the webpage. setAllowUniversalAccessFromFileURLs
allows us to use the file://
protocol to read files on the system.
The remaining code basically checks if the provided URL has /web
or /webview
path in it and if it does have either, it then checks if there’s a query parameter url
and then webview.loadUrl
loads the given URL.
So in short, there is no sanitization of the URL provided using the deep link so we can open arbitrary websites we control and run javascript. We will exploit it with adb
the first command being:
adb shell am start -a android.intent.action.VIEW -d 'insecureshop://com.insecureshop/web?url=http://example.com'
-a
option is used to specify the action, -d
is for the data passed to that action.
Here we loaded arbitrary URLs into the webview.
adb shell am start -a android.intent.action.VIEW -d 'insecureshop://com.insecureshop/web?url=file:///etc/hosts'
Here we managed to read the /etc/hosts
file on the system.
BeetleBug
BeetleBug is another vulnerable APK but with a CTF-like behavior. In the biometric flag we need to bypass the fingerprint validation using a deep link:
Let’s go through the same steps we did to find the deep link,
We can see the deep link used in the DeepLinkAccountActivity
and it defines https://beetlebug.com/account
deep link. Let’s go and see how the deep link is handled.
The code here is simple, if the deep link is triggered, we bypass the fingerprint validation and go straight to the account page to get the flag. So, let’s use the deep link while having the fingerprint activity running.
adb shell am start -n app.beetlebug/.ctf.DeeplinkAccountActivity -d 'https://beetlebug.com/account'
-n
option is used to access the activities relevant to the package name. Once we hit enter on our shell we get the flag and successfully bypassed the fingerprint validation.
That is it, if you reached this far, I hope you learned something new, and stay tuned for more Android articles as I study.