Deep Link Exploitation: Introduction & Open/unvalidated Redirection
What is a Deep Link?
A deep link is a link that takes you to a specific content. Most web links are deep links.
In Android, A deep link is a link that takes you directly to a specific destination within an app.
Types of Deep links in Android
There are 2 types of deep links in android and are classified as Explicit and Implicit deep links.
Explicit Deep Link
An explicit deep link is a single instance of a deep link that uses a PendingIntent
to take users to a specific location within your app.
An Explicit deep link is a deep link created by the same application when clicked, takes you to the content directly within the application.
Ex: A notification or An app widget
Implicit Deep Link
An implicit deep link refers to a specific destination in an app when the deep link is invoked.
An Implicit deep link is a deep link in the form of URI when clicked, takes you to the content directly within the respected application.
Ex: when a user clicks a link, Android can then open your app to the corresponding destination (Play store link).
Deep links in Android
All Deep links related to android are stored in AndroidManifest.xml File.
To create a Deep link to your app content, An intent filter containing the elements and attribute values are added to the AndroidManifest.xml file.
Before going to the elements and attributes, let us see what is an Intent filter.
An Intent is an object passed to launch an activity or get an existing activity to do something new.While an Intent filter describes a capability of the component(like activities, services, and broadcast receivers)
An Intent
is a messaging object you can use to request an action from one app component to another app component. Although intents facilitate communication between components in several ways, there are three fundamental use cases:
- Starting an activity
An Activity
represents a single screen in an app. You can start a new instance of an Activity
by passing an Intent
to startActivity()
. The Intent
describes the activity to start and carries any necessary data.
- Starting a service
A Service
is a component that performs operations in the background without a user interface. With Android 5.0 (API level 21) and later, you can start a service with JobScheduler
.
For versions earlier than Android 5.0 (API level 21), you can start a service by using methods of the Service
class. You can start a service to perform a one-time operation (such as downloading a file) by passing an Intent
to startService()
.
- Delivering a broadcast
A broadcast is a message that any app can receive. The system delivers various broadcasts for system events, such as when the system boots up or the device starts charging. You can deliver a broadcast to other apps by passing an Intent
to sendBroadcast()
or sendOrderedBroadcast()
.
The following XML snippet shows how you might specify an intent filter in your manifest for deep linking. The URIs “example://gizmos”
and “http://www.example.com/gizmos”
both resolve to this activity.
In the above image, we can see the deep link for an activity.
- The URIs
“example://gizmos”
and“http://www.example.com/gizmos”
both resolve to the activity named”com.example.android.GizmosActivity”
. - Intent-filter defines the capability of a activity component based on the type of URI.
<action>
Specify theACTION_VIEW
intent action, so that the intent filter can be reached from Google, DuckDuckGo or Any other Search Engine.<category>
Include theBROWSABLE
category. It is required in order for the intent filter to be accessible from a web browser. Without it, clicking a link in a browser cannot resolve to your app.
Also include the DEFAULT
category. This allows your app to respond to implicit intents. Without this, the activity can be started only if the intent specifies your app component name.
5. Add one or more <data>
tags, each of which represents a URI format that resolves to the activity. At minimum, the <data>
tag must include the android:scheme
attribute.
You can add more attributes to further refine the type of URI that the activity accepts. For example, you might have multiple activities that accept similar URIs, but which differ simply based on the path name. In this case, use the android:path
attribute or its pathPattern
or pathPrefix
variants to differentiate which activity the system should open for different URI paths.
DeepLink: Open/unvalidated Redirection
Demo Time
For this demo, we will be using the intentionally vulnerable android application called InsecureShop.
As we learn’t all deeplinks in android are stored in AndroidManifest.xml file, let us start by opening the apk in jadx-gui to read the manifest.xml.
From the above image, we now know that DeepLink will be handled based on the data tag defined in the intent filter i.e., android:scheme
must be present.
so let us search for the android:scheme
in the manifest file and can see we found only 1 deeplink.
from the above image we can understand that the deeplink invokes webview
by looking at the activity name. if you don’t remember what webview is, then check here.
The above uri will look like insecureshop://com.insecureshop
which invokes the webview activity. In Jadx, hold ctrl
and click on the activity name to open the code in new tab.
onCreate()
is a life cycle event in Android. There are 6 core set of life cycle events in Android’s activity lifecycleonCreate()
,onStart()
,onResume()
,onPause()
,onStop()
, andonDestroy()
which are self-explanatory.webview
settings for the defined webview activity.getIntent()
fetches the intent and stores inintent object
.intent.getData()
fetches the uri and stores inuri object
and checks if uri is empty.
- checks for path if it has
/web
in it and execute the respective code. - checks for path if it has
/webview
in it and execute the respective code. - finish the checks, if both check fails and webview will not be loaded.
if 1 or 2 passes, it will fetch the uri and extract the value from the url
query and store it on data
variable and will be loaded via webview.
From the above image, we will try to complete the uri to load the arbitrary web page in the webview.
insecureshop://com.insecureshop/web?url=https://3kal.medium.com
(or)
insecureshop://com.insecureshop/webview?url=https://3kal.medium.com
we will use ADB
to initiate the webview with our uri and we need to be logged into the insecureshop
application.
if you are not able to find the credentials, then here it is shopuser:!ns3csh0p
, once we login the screen looks like below.
Using ADB we launch webview activity by passing the uri as data to it.
adb shell am start -W -a android.intent.action.VIEW -d “insecureshop://com.insecureshop/web?url=https://3kal.medium.com"
Webview loads the arbitrary uri as shown below:
There are so many issues that can be exploited via deeplinks, which we will see in future articles.