深度链接漏洞
深度链接概述
深度链接是一种处理特定类型链接并将用户直接发送到应用的机制,例如发送到特定的 Activity。Android 允许开发者创建两种类型的链接:
深度链接
Android 应用链接
深度链接
深度链接是将用户直接带到应用中特定内容的 URL。例如,example://myapp
深度链接可用于启动 MainActivity
。
深度链接通过添加 Intent 过滤器 来设置,用户根据从传入 Intent 中提取的数据被引导到正确的 Activity。因此,多个应用能够处理相同的深度链接(Intent)。在这种情况下,用户可能不会直接进入特定的应用,需要选择一个应用,参见 Intent 解析 部分。
以下 XML 代码片段显示了清单中用于深度链接的 Intent 过滤器示例,其中 example://myapp
URI 被解析为 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" />
<!-- 接受以 "example://myapp" 开头的 URI -->
<data android:scheme="example"
android:host="myapp" />
</intent-filter>
</activity>
Android 应用链接
Android 应用链接是一种特殊类型的深度链接,允许网站 URL 立即在应用中打开相应内容(不需要用户选择应用)。如果用户不希望应用成为默认处理程序,他们可以从设备的系统设置中覆盖此行为。
Android 应用链接通过添加 Intent 过滤器 来设置,这些过滤器使用 http/https
URL 打开应用内容,并验证应用是否被允许打开这些网站 URL。验证需要以下步骤:
在清单中请求自动应用链接验证。这向 Android 系统发出信号,它应该验证应用是否属于 Intent 过滤器中使用的 URL 域。
通过在以下位置托管 Digital Asset Links JSON 文件来声明网站和 Intent 过滤器之间的关系:
https://domain.name/.well-known/assetlinks.json
如果系统成功验证应用被允许打开 URL,系统会自动将此 URL Intent 路由到应用。
以下 XML 代码片段显示了清单中用于应用链接的 Intent 过滤器示例,其中 https://example.com
URI 被解析为 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" />
<!-- 接受以 "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
用户体验
可能显示消歧对话框,供用户选择哪个应用打开链接
无对话框;应用打开以处理网站链接
兼容性
所有 Android 版本
Android 6.0 及更高版本
安全问题
访问任意组件
应用可以实现自己的 Intent 解析器来处理深度链接,使用 JSON 对象、字符串或字节数组,这些对象可能会扩展 Serializable 和 Parcelable 对象并允许设置不安全的标志。
例如,以下深度链接解析器将字节数组转换为 Parcel 并从中读取 Intent:
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:
<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>
参考资料:
在 WebView 中打开任意 URL
如果应用根据深度链接中的参数在 WebView 中打开 URL,您可以尝试绕过 URL 验证并打开任意 URL。这可用于执行任意 JavaScript、窃取敏感数据、访问任意组件并与其他弱点链式攻击。
参考资料:
绕过本地身份验证
应用可以在本地身份验证(密码/生物识别)之前处理深度链接,有时这可能导致用户被直接推送到 Activity 而无需本地身份验证。这可能需要您简单地遵循深度链接,或滥用参数/功能,试图获得异常条件,例如验证失败或中途中断流程。
参考资料:
不安全的参数处理
深度链接允许用户向应用提供参数,这些参数可以用作执行本地操作、API 请求等时的参数。因此,如果这些参数没有得到适当的验证,攻击者可以利用它们获利(直到 RCE)。
例如,假设应用通过以下流程基于 http/https URL 打开本地文件:
用户发送链接
https://website.com/file.pdf
应用解析 URL 并检索 URL 路径:
file.pdf
应用将硬编码的临时文件夹与
file.pdf
连接:/data/data/com.vulnerable-app/temp-files/file.pdf
应用从
https://website.com/file.pdf
下载 PDF 文件并将其保存到/data/data/com.vulnerable-app/temp-files/file.pdf
应用为用户打开下载的文件
在这种情况下,攻击者能够使用路径遍历重写包内的任意文件:https://website.com/x/..%2F..%2Fdatabases/secret.db
。
参考资料:
无需确认执行不安全操作
有时应用允许用户通过深度链接执行不安全操作,例如修改数据、拨打电话、购买订阅等。如果这些操作不需要用户的额外确认,您可以执行类似 CSRF 的攻击。
例如,如果应用允许经过身份验证的用户通过 myapp://user?email=<email>
深度链接更改其电子邮件,您可以通过让他们访问以下页面来将受害者的电子邮件更改为您自己的:
<!DOCTYPE html>
<html>
<script>location.href = "myapp://[email protected]";</script>
</html>
参考资料:
参考资料
最后更新于