Android13 加强Intent filters 的安全性

作者:??TechMerger???? 时间:2022-06-17 03:15:55 

前言:

在看这个变更之前,我们需要回忆下 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,并且不是上述豁免对象的话,需要做些检查和必要的修改。

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

  • 作为启动方:

    • startActivity()

    • startActivityForResult()

    • sendBroadcast()

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

    • 该 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)

    来源:https://juejin.cn/post/7099450024525824037

    标签:Android13,加强,Intent,filters,安全性
    0
    投稿

    猜你喜欢

  • 关于Springboot+gateway整合依赖并处理依赖冲突问题

    2023-10-23 21:13:56
  • C#实现观察者模式(Observer Pattern)的两种方式

    2023-06-20 21:05:18
  • C++中静态成员函数与静态成员变量(static )

    2021-11-08 07:31:38
  • 使用BufferedReader读取本地文件的操作

    2021-10-15 03:22:47
  • C#中float的取值范围和精度分析

    2023-05-19 01:03:21
  • WPF仿三星手机充电界面实现代码

    2021-09-16 06:20:44
  • android跑马灯出现重复跳动以及不滚动问题的解决方法

    2023-07-24 00:33:48
  • Android Shader应用开发之霓虹闪烁文字效果

    2022-09-11 16:43:20
  • Spring使用AOP完成统一结果封装实例demo

    2021-12-16 18:49:06
  • spring boot项目快速构建的全步骤

    2023-11-16 21:16:38
  • SpringBoot启动yaml报错的解决

    2021-09-09 22:58:14
  • C# 两种方式反编译修改源码(dnspy,ildasm & ilasm)

    2022-04-29 18:48:56
  • Android 获取手机信息实例详解

    2021-08-21 00:22:34
  • C#结合AForge实现摄像头录像

    2021-06-28 03:53:51
  • Spring Boot接口限流的常用算法及特点

    2023-12-20 05:16:30
  • C++编程中用put输出单个字符和cin输入流的用法

    2023-05-28 06:14:49
  • Android性能优化之Bitmap图片优化详解

    2023-08-06 02:54:23
  • C#软件注册码的实现代码

    2021-10-14 06:14:38
  • Android10填坑适配指南(实际经验代码)

    2022-10-05 19:51:19
  • 一篇文章带你了解JVM垃圾回收

    2023-08-06 23:42:20
  • asp之家 软件编程 m.aspxhome.com