Deep Linking Vulnerabilities

Deep linking overview

Deep linking is a mechanism that processes specific types of links and sends users directly to an app, for example, to a particular activity. Android allows developers to create two types of links:

  • Deep link

  • Android App Link

Deep link is a URL that takes users directly to specific content in an app. For example, the example://myapp deep link can be used to start MainActivity.

Deep links are set up by adding intent filters and users are driven to the right activity based on the data extracted from incoming intents. Therefore, several apps are able to handle the same deep links (intents). In this case, users might not go directly to a particular app and they need to select an app, see the Intent resolution section.

The following XML snippet shows an example of an intent filter in a manifest for deep linking, where the example://myapp 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" />
        <!-- Accepts URIs that begin with "example://myapp -->
        <data android:scheme="example"
              android:host="myapp" />
    </intent-filter>
</activity>

Android App Links is a special type of deep link that allows website URLs to immediately open the corresponding content in an app (without requiring the user to select the app). If the user doesn't want the app to be the default handler, they can override this behavior from their device's system settings.

Android App Links are set up by adding intent filters that open an app content using http/https URLs and verifying that an app is allowed to open these website URLs. The verifying is required the following steps:

  • Request automatic app link verification in a manifest. This signals to the Android system that it should verify an app belongs to the URL domain used in intent filters.

  • Declare the relationship between a website and intent filters by hosting a Digital Asset Links JSON file at the following location:

    https://domain.name/.well-known/assetlinks.json

If the system successfully verifies that an app is allowed to open a URL, the system automatically routes this URL intents to the app.

The following XML snippet shows an example of an intent filter in a manifest for app linking, where the https://example.com URI is resolved to the MainActivity:

<activity android:name="MainActivity">
    <intent-filter android:autoVerify="true">
        <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 "https://example.com/ -->
        <data android:scheme="https" 
              android:host="example.com" />
    </intent-filter>
</activity>
#Deep linksApp links

Intent URL scheme

http, https, or a custom scheme

Requires http or https

Intent action

Any action

Requires android.intent.action.VIEW

Intent category

Any category

Requires android.intent.category.BROWSABLE and android.intent.category.DEFAULT

Link verification

None

Requires a Digital Asset Links file served on a website with HTTPS

User experience

May show a disambiguation dialog for the user to select which app to open the link

No dialog; an app opens to handle website links

Compatibility

All Android versions

Android 6.0 and higher

Security issues

Access arbitrary components

An app can implement its own intent parser to handle deeplinks using JSON objects, strings or byte arrays that may expand Serializable and Parcelable objects and allow to set insecure flags.

For example, the following deeplink parser converts a byte array to Parcel and read an intent from it:

Uri deeplinkUri = getIntent().getData();
if (deeplinkUri.toString().startsWith("deeplink://handle/")) {
    byte[] handle = Base64.decode(deeplinkUri.getQueryParameter("param"), 0);
    Parcel parcel = Parcel.obtain();
    parcel.unmarshall(handle, 0, handle.length);
    startActivity((Intent) parcel.readParcelable(getClassLoader()));
}

Deeplinks as well as app links can use the https scheme, and developers can configure an intent filter for deeplinks instead of app links. As a result, you can create an app that will handle the same deeplinks and intercept intents:

<intent-filter android:priority="999">
	<action android:name="android.intent.action.VIEW" />
	<category android:name="android.intent.category.DEFAULT" />
	<category android:name="android.intent.category.BROWSABLE" />
	<data android:scheme="https" />
	<data android:host="myapp.link" />
</intent-filter>

References:

Arbitrary URL opening in WebView

If an app opens URL in WebView based on parameters from a deeplink you can try to bypass a URL validation and open arbitrary URLs. This can be used to execute arbitrary JavaScript, steal sensitive data, access arbitrary components and chain with other weaknesses.

References:

Bypass local authentication

Apps can handle deeplinks before local authentication (passcode/biometrics) and sometimes this can lead to a direct user being pushed into an activity without local authentication. This may require you to simply follow a deeplink, or abuse parameters / functionality, trying to get exceptional conditions, such as failing validation or interrupting a flow in the middle.

References:

Insecure parameter handling

Deeplinks allows users to provide parameters to an application that can be used as parameters when performing local actions, requests to API, etc. Therefore, if these parameters are not properly validated, an attacker can use them for profit (up to RCE).

For instance, suppose an application opens local files based on http/https URLs by the next flow:

  1. A user send the link https://website.com/file.pdf

  2. An application parses the URL and retrieves the URL path: file.pdf

  3. An application joins a hard-coded temp folder with file.pdf: /data/data/com.vulnerable-app/temp-files/file.pdf

  4. An application downloads the PDF file from https://website.com/file.pdf and save them to /data/data/com.vulnerable-app/temp-files/file.pdf

  5. An application opens downloaded file for a user

In such case, an attacker is able to rewrite an arbitrary file within the package using path traversal: https://website.com/x/..%2F..%2Fdatabases/secret.db.

References:

Perform unsafe actions without confirmation

Sometimes apps allow users to perform unsafe actions through deeplinks, such as modifying data, doing a call, buying a subscription and etc. If these actions do not require additional confirmation from a user, you can perform a CSRF-like attack.

For example, if an app allows authenticated users to change their email through the myapp://user?email=<email> deeplink, you can change the victim's email to your own by making them visit the following page:

<!DOCTYPE html>
<html>
    <script>location.href = "myapp://user?email=attacker@attacker-website.com";</script>
</html>

References:

References

Last updated