Android 13 针对 Intent filters 安全的再加强

简介: Android 13 针对 Intent filters 安全的再加强

在看这个变更之前,我们需要回忆下 Android 12 的一个安全性变更, 即声明了 <intent-filter> 的Activity、BroadcastReceiver、Service 必须声明 android:exported, 否则将会无法被启动。


Android 12 的这个变更是为了防止开发者在不知情的情况下,声明了一个 intent-filter 就会使得这些组件对外公开,一定程度下强化了安全性。


但是却漏掉了显示 Intent 启动和 Broadcast Receiver 动态注册两种情况,便在 13 中分别推出了两项变更来进行加强。


Intent filters block non- -matching intents

Safer exporting of context- -registered receivers

Intent filters block non-matching intents

Android 13 开始 Intent 过滤器会屏蔽不匹配的 intent,即便是指定了 Component 的显示启动。

在 13 以前:

开发者想给 Component 添加 支持


这个 需要公开给外部 App 使用,便设定了 Component exported 为 true


这时候该 Component 就出现了一个安全漏洞:外部 App 使用不同于 中声明的 Action,甚至 mimeType 都不匹配均可以启动它


也许你觉得这并没有什么,但是如果 App 只针对 过来的 Route 做了安全校验,就造成了校验上的疏漏。

具体变更

假如我们提供了的 Activity 像如下一样声明:

<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.TEST" />
        <data android:mimeType="vnd.android.cursor.dir/event"/>
    </intent-filter>
</activity>

在 13 之前,其他 App 采用了显示启动,即便是错误的 ACTION 是可以正常启动我们的 Activity。

private fun testIntentFilters() {
    Intent().setComponent(
        ComponentName("com.example.demoapplication",
            "com.example.demoapplication.MainActivity")
    ).apply {
        action = "android.intent.action.TEST_A"
        startActivity(this)
    }
}

而运行在 13 上的话,将无法启动并会发生如下错误:


PackageManager: Intent does not match component’s intent filter: Intent { act=android.intent.action.TEST_A cmp=com.example.demoapplication/.MainActivity }


PackageManager: Access blocked: ComponentInfo{com.example.demoapplication/com.example.demoapplication.MainActivity}

除了 ACTION 修改正确以外,data 也要满足即 Intent-filter 完全符合才可以启动。

private fun testIntentFilters() {
    Intent().setComponent(
        ComponentName("com.example.demoapplication",
            "com.example.demoapplication.MainActivity")
    ).apply {
        action = "android.intent.action.TEST"
        data = CalendarContract.Events.CONTENT_URI
        startActivity(this)
    }
}

豁免

如下的几种场景下的 Intent 并不在本次变更的影响范围内:


目标 Component 没有声明 <intent-filter>


同一个 App 内部发出的 Intent


系统发出的 Intent,包括 SystemServer、采用 System UID 的系统 App


Root 进程发出的 Intent

适配办法

如果目标运行的版本基于 Android 13,并且不是上述豁免对象的话,需要做些检查和必要的修改。


按照启动方和目标方两种情况进行适配办法的探讨:


作为启动方:

是否存在采用显示 Intent 方式启动其他 App 或发送广播的情况

startActivity()

startActivityForResult()

sendBroadcast()

该 Component 是否声明了 <intent-filter>

防止其 Target 升级到了 Android 13 无法正常启动,需要注意 Intent 的 action、data 等信息是否准确

作为目标方:

Target 是否需要升级到 Android 13

是否对外提供了 Component 并声明了 <intent-filter>

防止无法被正常启动,需要告知启动方 <intent-filter> 的信息

残留

13 上实测发现 Service 组件在显示启动下,即便是错误的 ACTION,仍能被正常启动。这是有意为之还是 Beta 版漏洞,源码尚未公开,原因未知。

  • startService()
  • startForegroundService()
  • bindService()

Safer exporting of context-registered receivers

为了帮助提高运行时接收器的安全性,Android 13 允许您指定您应用中的特定广播接收器是否应被导出以及是否对设备上的其他应用可见。


如果导出广播接收器,其他应用将可以向您的应用发送不受保护的广播。此导出配置在以 Android 13 或更高版本为目标平台的应用中可用,有助于防止一个主要的应用漏洞来源。

具体变更

TargetSDK 升级到 Android13 的 App 在动态注册 Receiver 的时候不指明该 flag,那么会收到如下的 crash:


java.lang.SecurityException: com.example.demoapplication: One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn’t being registered exclusively for system broadcasts


目前上述限制不是默认生效的,需要开启如下兼容性变更:


开发者选项 -> App Compatibility Changes -> Your App -> DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED

另外,当你的 Receiver 声明了 RECEIVER_NOT_EXPORTED 的话,其他 App 向其发送广播会失败,并打印如下日志提醒你的 Receiver 需要公开:


BroadcastQueue: Exported Denial: sending Intent { act=com.example.demoapplication.RECEIVER flg=0x10 }, action: com.example.demoapplication.RECEIVER from com.example.tiramisu_demo (uid=10161)


due to receiver ProcessRecord{8e5f11c 16942:com.example.demoapplication/u0a158} (uid 10158) not specifying RECEIVER_EXPORTED

豁免

需要留意的是,系统级广播是受保护的,普通 App 没有权限发送。

所以只是监听系统广播的话,动态注册的 Receiver 无需指定上述 flag。即便指定了 RECEIVER_NOT_EXPORTED,和静态注册方式一致也能正常接收、不受影响。

适配办法

找到所有动态注册 Broadcast Receiver 的代码。如果监听的包含非系统广播,请根据是否公开给其他 App 的需要使用来添加 flag 的声明。

  • RECEIVER_EXPORTED
  • RECEIVER_NOT_EXPORTED
context.registerReceiver(sharedBroadcastReceiver, intentFilter,
    RECEIVER_EXPORTED)
context.registerReceiver(privateBroadcastReceiver, intentFilter,
    RECEIVER_NOT_EXPORTED)

结语

无论是针对 Intent Fitler 匹配的要求升级还是动态注册的 Receiver Flag,都是为了增强组件安全。希望开发者在对待这些习以为常的三大组件时,多些思考、避免漏洞百出。

参考文章

相关文章
|
3月前
|
Android开发 开发者
Android基础知识:什么是Intent?有哪些类型的Intent?
Android基础知识:什么是Intent?有哪些类型的Intent?
247 0
|
3月前
|
安全 Linux Android开发
Android 安全功能
Android 安全功能
59 0
|
3月前
|
安全 Linux Android开发
Android安全启动学习(一):AVB校验是什么?
Android安全启动学习(一):AVB校验是什么?
251 0
|
3月前
|
存储 安全 Linux
Android安全启动学习(四):device-mapper-verity (dm-verity)和哈希树
Android安全启动学习(四):device-mapper-verity (dm-verity)和哈希树
237 0
|
10月前
|
存储 SQL 人工智能
Android Activity启动流程一:从Intent到Activity创建
Android Activity启动流程一:从Intent到Activity创建
|
22天前
|
存储 安全 数据安全/隐私保护
🔎Android安全攻防实战!守护你的应用数据安全,让用户放心使用!🛡️
【7月更文挑战第28天】在移动应用盛行的时代,确保Android应用安全性至关重要。本文以问答形式探讨了主要安全威胁(如逆向工程、数据窃取)及其对策。建议使用代码混淆、签名验证、数据加密等技术来增强应用保护。此外,还推荐了加密API、HTTPS通信、代码审计等措施来进一步加强安全性。综上所述,全面的安全策略对于构建安全可靠的应用环境必不可少。#Android #应用安全 #代码混淆 #数据加密
26 3
|
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。
|
1月前
|
存储 安全 Android开发
安卓应用开发的安全之道
【7月更文挑战第4天】在数字时代,移动应用的安全性至关重要。本文将深入探讨在安卓平台上开发安全应用的最佳实践,包括代码混淆、数据存储加密、网络通信安全、权限管理以及定期的安全审计和更新策略。通过这些措施,开发者可以显著提高他们的应用抵御恶意攻击的能力,保护用户数据免受侵害。
|
2月前
|
安全 网络协议 网络安全
程序与技术分享:Android应用安全之数据传输安全
程序与技术分享:Android应用安全之数据传输安全
|
3月前
|
定位技术 Android开发
Intent在Android中的几种用法
Intent在Android中的几种用法
33 1