谈一谈 Android 嵌套 Intent 以及解决方案

简介: 谈一谈 Android 嵌套 Intent 以及解决方案

翻译自 Nicole Borrelli 在 Medium 上的 post 《Android Nesting Intents》。


你的 App 是否在某些情况下对外提供了一个 Service 来执行启动其他 App 的 Activity 组件的回调。比如说,接收的 Intent 请求会以 extra 参数的形式内嵌着的其他 Intent ,而这个 Intent 参数会被用作 startActivity() 调用。


你有没有意识到这种做法会让你的 App 变得脆弱、易攻击?


如下的内容将解释采用这种做法会带来的问题,并提供一个解决方案,来确保你的 App 能以更加安全的方式来实现相同的功能。

带来的问题

我们期望这种类型的交互,会按照示意图的设计来进行:

1832b220aa754cd18c504acc7686a560.png

上述流程图展示了如何将一个用来启动回调 Activity 的 Intent 添加到启动 Service 的 Intent 中,以及该 Service 被用作启动参数提供的 Activity。


Client App 为 ClientCallbackActivity 创建了一个 Intent 实例并将它以 extra 形式添加到了用于其他 Provider App 的 ApiService 的 Intent 属性中。Provider App 处理完该请求后将使用 Client App 提供的 Intent 来启动目标 Activity。


❗️这里需要注意的是 Provider App 调用的 startActivity() 采用的是它自己的 Context,这将带来两个欠佳的后果。


因为 ClientCallbackActivity 将被外部的 Provider App 启动,所以它需要标记为对外可见即 exported,而这将允许 Provider App 以外的任何其他 App 都可以启动它

传递给 ApiService 的嵌套 Intent 可被用来启动 Provider App 的任何 Activity,包括私有的、有潜在敏感信息的、对外不可见的所有 Activity!

为了进一步说明,请思考一下如果调用方 App 提供的内嵌 Intent 并非指向自己的 Activity,相反其指向了 Provider App 内部的私有 Activity,会发生什么?

1832b220aa754cd18c504acc7686a560.png

上述流程图展示了一个精心构造的 Intent 如何被用来启动 Provider App 的 ApiSensitiveActivity,尽管它对外不可见也不应该被其他 App 启动。


因为采用了嵌套 Intent,对于 Provider App 来说很难去防止其他 App 去访问它的私有的、有潜在敏感信息的 Activity 们。而且 Provider App 直接使用了 startActivity() 去处理 Intent,即便ApiSensitiveActivity 未被声明为对外可见仍然可以被启动。

解决方案:PendingIntent

解决方案很简单:Provider App 不要接收 Intent,而是接收 PendingIntent。原因在于 Intent 和 PendingIntent 的区别: PendingIntent 总是使用创建它的 Context 进行 Intent 的处理。

1832b220aa754cd18c504acc7686a560.png

上述流程图展示接收 PendingIntent 的话如何使用 App 创建它的 Context 进行处理,这可以阻止访问 Provider App 中非对外可见的 Activity 们。


因为回调提供的是 PendingIntent 对象,当 Provider App 调用它的 send() 时,startActivity() 请求会被当做 Attacker App 这一方进行处理。而 Attacker App 并不具备调用 Provider App 中 ApiSensitiveActivity 的特权,所以系统将会阻止这个启动请求。


对于 Provider App 来说这必然很有好处,但是我们自己的 Client App 呢?那么,如之前所说我们提供的是 PendingIntent 类型,ClientCallbackActivity 改为私有、非公开的话一样可以启动。也就是说,这种做法增强了双方 App 的安全。


如果你熟悉 Notification、Alarm Manager 等相关的 API,你应该知道它们采用 PendingIntent 来激活某些操作以及向 App 发出 alarm 通知。它始终以创建它的 App 身份进行处理,这也是系统选择 PendingIntent 而非一般 Intent 的原因。

结语

无论是对于 Client App 还是对于 Provider App,采用 Intent 这种机制来实现 Activity 启动回调的做法会导致双方 App 的安全隐患。这源自于 Intent 会在调用它的 App 上下文进行处理。而这个上下文造成了 Provider App 中非公开 Activity 被启动的可能性,同时也迫使 Client App 必须对外公开处理回调的 Activity。


相较之下,PendingIntent 会在创建它的上下文进行处理。这将允许 Provider App 可以自由使用、不会对外暴露 Activity,同时可以使得 Client App 指定任意 Activity 来处理回调,包括非公开 Activity。


可以查看 《不安全的 intent 启动》 这篇文章了解 Android 系统如何帮助 App 减少嵌套 Intent 的影响。

参考


相关文章
|
3月前
|
XML Android开发 数据格式
android点击FrameLayout、LinearLayout等父布局没响应的原因以及解决方案
android点击FrameLayout、LinearLayout等父布局没响应的原因以及解决方案
92 2
|
3月前
|
安全 Shell Android开发
Android系统 init.rc sys/class系统节点写不进解决方案和原理分析
Android系统 init.rc sys/class系统节点写不进解决方案和原理分析
122 0
|
3月前
|
Android开发 开发者
Android基础知识:什么是Intent?有哪些类型的Intent?
Android基础知识:什么是Intent?有哪些类型的Intent?
247 0
|
10月前
|
存储 SQL 人工智能
Android Activity启动流程一:从Intent到Activity创建
Android Activity启动流程一:从Intent到Activity创建
|
6天前
|
Android开发
Android编译出现Warning: Mapping new ns to old ns的解决方案
Android编译出现Warning: Mapping new ns to old ns的解决方案
13 3
|
18天前
|
前端开发 JavaScript Android开发
探索Android和iOS开发中的跨平台解决方案
【8月更文挑战第1天】随着移动应用市场的不断扩张,开发者面临一个共同的挑战——如何高效地为多个平台创建和维护应用程序。本文将深入探讨跨平台开发工具,特别是Flutter和React Native,通过比较它们的优势和限制,并辅以实际代码示例,揭示这些工具如何帮助开发者在保持高性能的同时,实现代码的最大化重用。
|
17天前
|
Java Android开发 UED
安卓scheme_url调端:如果手机上多个app都注册了 http或者https 的 intent。 调端的时候,调起哪个app呢?
当多个Android应用注册了相同的URL Scheme(如http或https)时,系统会在尝试打开这类链接时展示一个选择对话框,让用户挑选偏好应用。若用户选择“始终”使用某个应用,则后续相同链接将直接由该应用处理,无需再次选择。本文以App A与App B为例,展示了如何在`AndroidManifest.xml`中配置对http与https的支持,并提供了从其他应用发起调用的示例代码。此外,还讨论了如何在系统设置中管理这些默认应用选择,以及建议开发者为避免冲突应注册更独特的Scheme。
|
2月前
|
编解码 Android开发
Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题
Android 解决TextView多行滑动与NestedScrollView嵌套滑动冲突的问题
28 0
|
3月前
|
定位技术 Android开发
Intent在Android中的几种用法
Intent在Android中的几种用法
33 1
|
3月前
|
Java Android开发
Android桌面快捷方式图标生成与删除 使用Intent与launcher交互
Android桌面快捷方式图标生成与删除 使用Intent与launcher交互
57 1