> For the complete documentation index, see [llms.txt](https://gitbook.cdxiaodong.life/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gitbook.cdxiaodong.life/android-ying-yong-an-quan/intent-vulnerabilities/deep-linking-vulnerabilities.md).

# 深度链接漏洞

## 深度链接概述

深度链接是一种处理特定类型链接并将用户直接发送到应用的机制，例如发送到特定的 Activity。Android 允许开发者创建两种类型的链接：

* 深度链接
* Android 应用链接

### 深度链接

深度链接是将用户直接带到应用中特定内容的 URL。例如，`example://myapp` 深度链接可用于启动 `MainActivity`。

深度链接通过添加 [Intent 过滤器](/android-ying-yong-an-quan/intent-vulnerabilities.md#intent-filter) 来设置，用户根据从传入 Intent 中提取的数据被引导到正确的 Activity。因此，多个应用能够处理相同的深度链接（Intent）。在这种情况下，用户可能不会直接进入特定的应用，需要选择一个应用，参见 [Intent 解析](/android-ying-yong-an-quan/intent-vulnerabilities.md#intent-resolution) 部分。

以下 XML 代码片段显示了清单中用于深度链接的 Intent 过滤器示例，其中 `example://myapp` URI 被解析为 `MainActivity`：

```xml
<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" />
        <!-- 接受以 "example://myapp" 开头的 URI -->
        <data android:scheme="example"
              android:host="myapp" />
    </intent-filter>
</activity>
```

### Android 应用链接

Android 应用链接是一种特殊类型的深度链接，允许网站 URL 立即在应用中打开相应内容（不需要用户选择应用）。如果用户不希望应用成为默认处理程序，他们可以从设备的系统设置中覆盖此行为。

Android 应用链接通过添加 [Intent 过滤器](/android-ying-yong-an-quan/intent-vulnerabilities.md#intent-filter) 来设置，这些过滤器使用 `http/https` URL 打开应用内容，并验证应用是否被允许打开这些网站 URL。验证需要以下步骤：

* 在清单中请求[自动应用链接验证](https://developer.android.com/training/app-links/verify-site-associations#request-verify)。这向 Android 系统发出信号，它应该验证应用是否属于 Intent 过滤器中使用的 URL 域。
* 通过在以下位置托管 [Digital Asset Links](https://developers.google.com/digital-asset-links/v1/getting-started) JSON 文件来声明网站和 Intent 过滤器之间的关系：

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

如果系统成功验证应用被允许打开 URL，系统会自动将此 URL Intent 路由到应用。

以下 XML 代码片段显示了清单中用于应用链接的 Intent 过滤器示例，其中 `https://example.com` URI 被解析为 `MainActivity`：

```xml
<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" />
        <!-- 接受以 "https://example.com/ 开头的 URI -->
        <data android:scheme="https" 
              android:host="example.com" />
    </intent-filter>
</activity>
```

### 深度链接和应用链接之间的区别

| #             | 深度链接                    | 应用链接                                                                                                               |
| ------------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------ |
| Intent URL 方案 | `http`、`https` 或自定义方案   | 需要 `http` 或 `https`                                                                                                |
| Intent 操作     | 任何操作                    | 需要 `android.intent.action.VIEW`                                                                                    |
| Intent 类别     | 任何类别                    | 需要 `android.intent.category.BROWSABLE` 和 `android.intent.category.DEFAULT`                                         |
| 链接验证          | 无                       | 需要在使用 HTTPS 的网站上托管的 [Digital Asset Links](https://developers.google.com/digital-asset-links/v1/getting-started) 文件 |
| 用户体验          | 可能显示消歧对话框，供用户选择哪个应用打开链接 | 无对话框；应用打开以处理网站链接                                                                                                   |
| 兼容性           | 所有 Android 版本           | Android 6.0 及更高版本                                                                                                  |

## 安全问题

### 访问任意组件

应用可以实现自己的 Intent 解析器来处理深度链接，使用 JSON 对象、字符串或字节数组，这些对象可能会扩展 Serializable 和 Parcelable 对象并允许设置不安全的标志。

例如，以下深度链接解析器将字节数组转换为 Parcel 并从中读取 Intent：

```java
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()));
}
```

### 应用链接错误配置

深度链接和应用链接都可以使用 `https` 方案，开发者可以为深度链接而不是应用链接配置 Intent 过滤器。因此，您可以创建一个应用来处理相同的深度链接并拦截 Intent：

```xml
<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>
```

参考资料：

* [报告：通过拦截 Arrive 应用的魔术链接实现账户接管](https://hackerone.com/reports/855618)

### 在 WebView 中打开任意 URL

如果应用根据深度链接中的参数在 WebView 中打开 URL，您可以尝试绕过 URL 验证并打开任意 URL。这可用于执行任意 JavaScript、窃取敏感数据、访问任意组件并与其他弱点链式攻击。

参考资料：

* [WebView 漏洞：绕过 URL 验证](/android-ying-yong-an-quan/webview-vulnerabilities.md#bypass-url-validation)
* [报告：\[Grab Android/iOS\] 不安全的深度链接导致敏感信息泄露](https://hackerone.com/reports/401793)
* [文章：攻破 Facebook Android 应用](https://ash-king.co.uk/blog/facebook-bug-bounty-09-18)
* [文章：当等于不等于时，另一个 WebView 接管故事](https://valsamaras.medium.com/when-equal-is-not-another-webview-takeover-story-730be8d6e202)

### 绕过本地身份验证

应用可以在本地身份验证（密码/生物识别）之前处理深度链接，有时这可能导致用户被直接推送到 Activity 而无需本地身份验证。这可能需要您简单地遵循深度链接，或滥用参数/功能，试图获得异常条件，例如验证失败或中途中断流程。

参考资料：

* [报告：在 Android 应用中可能绕过生物识别安全功能 (com.shopify.mobile)](https://hackerone.com/reports/637194)

### 不安全的参数处理

深度链接允许用户向应用提供参数，这些参数可以用作执行本地操作、API 请求等时的参数。因此，如果这些参数没有得到适当的验证，攻击者可以利用它们获利（直到 RCE）。

例如，假设应用通过以下流程基于 http/https URL 打开本地文件：

1. 用户发送链接 `https://website.com/file.pdf`
2. 应用解析 URL 并检索 URL 路径：`file.pdf`
3. 应用将硬编码的临时文件夹与 `file.pdf` 连接：`/data/data/com.vulnerable-app/temp-files/file.pdf`
4. 应用从 `https://website.com/file.pdf` 下载 PDF 文件并将其保存到 `/data/data/com.vulnerable-app/temp-files/file.pdf`
5. 应用为用户打开下载的文件

在这种情况下，攻击者能够使用路径遍历重写包内的任意文件：`https://website.com/x/..%2F..%2Fdatabases/secret.db`。

参考资料：

* [文章：ADOBE ACROBAT READER FOR ANDROID 中的 RCE (CVE-2021-40724)](https://hulkvision.github.io/blog/post1/)

### 无需确认执行不安全操作

有时应用允许用户通过深度链接执行不安全操作，例如修改数据、拨打电话、购买订阅等。如果这些操作不需要用户的额外确认，您可以执行类似 CSRF 的攻击。

例如，如果应用允许经过身份验证的用户通过 `myapp://user?email=<email>` 深度链接更改其电子邮件，您可以通过让他们访问以下页面来将受害者的电子邮件更改为您自己的：

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

参考资料：

* [报告：Periscope Android 应用深度链接导致关注操作中的 CSRF](https://hackerone.com/reports/583987)
* [报告：解锁镜头时的 CSRF 导致镜头在无需用户交互的情况下被强制安装](https://hackerone.com/reports/1085336)

## 参考资料

* [Android 开发者：处理 Android 应用链接](https://developer.android.com/training/app-links)
* [Oversecured：Android 访问应用受保护组件](https://blog.oversecured.com/Android-Access-to-app-protected-components/)
