Android13 加强Intent filters 的安全性

目录
  • Intent filters block non-matching intents
    • 具体变更
    • 豁免
    • 适配办法
    • 残留
  • Safer exporting of context-registered receivers
    • 具体变更
    • 豁免
    • 适配办法
  • 结语

前言:

在看这个变更之前,我们需要回忆下 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,都是为了增强组件安全。希望开发者在对待这些习以为常的三大组件时,多些思考、避免漏洞百出。

到此这篇关于Android13 加强Intent filters 的安全性的文章就介绍到这了,更多相关Android Intent filters 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android开发之TextView使用intent传递信息,实现注册界面功能示例

    本文实例讲述了Android开发之TextView使用intent传递信息,实现注册界面功能.分享给大家供大家参考,具体如下: 使用intent在活动间传递值 首先是 MainActuvity 活动(注册界面 写完个人信息点击注册 ) 跳转到 In 活动 (通过 intent 获得 MainActivity 中的信息 ) 效果图如下: MainActivity 实现: Java代码: public class Home extends AppCompatActivity { //用于存放个人注册

  • Android使用Intent的Action和Data属性实现点击按钮跳转到拨打电话和发送短信界面

    场景 点击拨打电话按钮,跳转到拨打电话页面 点击发送短信按钮,跳转到发送短信页面 注: 实现 将布局改为LinearLayout,并通过android:orientation="vertical">设置为垂直布局,然后添加id属性. 然后添加两个按钮,并设置Id属性与显示文本. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="

  • Android中Activity的四种启动模式和onNewIntent()

    写在前面 Activity是Android四大组件之一,用于直接跟用户进行交互,本篇文章将介绍Activity的启动流程.用户启动Activity的方式大致有两种:一种是在桌面点击应用程序的图标,进入应用程序的主界面:另一种是在应用程序中,进入一个新的Activity.前者,桌面其实是系统应用launcher的界面,点击应用程序图标,会进行应用程序的主界面,实质是从一个应用的Activity进入另一个应用Activity. 因此,不管是从桌面进入应用主界面,还是在应用里进入一个新的Activit

  • Android Intent传递数据大小限制详解

    前言 在sendBroadcast,startActivity时,我们会用到Intent. Intent可以携带一些数据,比如基本类型数据int.Boolean,或是String,或是序列化对象,Parcelable与Serializable. Intent传递数据时,如果数据太大,可能会出现异常.比如App闪退,或是Intent发送不成功,logcat报错等等. 这就牵涉到一个问题:Intent 传递数据大小限制. Intent到底能够携带多少数据呢? 使用Intent传送数据时,可能会出现异

  • Android 嵌套 Intent 隐患及解决方案

    目录 带来的问题 解决方案:PendingIntent 结语 前言: 翻译自 Nicole Borrelli 在 Medium 上的 post <Android Nesting Intents>. 大家 App 是否在某些情况下对外提供了一个 Service 来执行启动其他 App 的 Activity 组件的回调.比如说,接收的 Intent 请求会以 extra 参数的形式内嵌着的其他 Intent ,而这个 Intent 参数会被用作 startActivity() 调用. 大家有没有意

  • Android中传值Intent与Bundle的区别小结

    前言 Bundle 翻译成中文的意思是"捆绑",常用在Activity间传递参数,之前一开始并不太待见,原因是Intent本身就可以传递,Intent.putExtra("key", value),为何还要用Bundle呢? 正巧小伙伴问Android传值Intent和Bundle区别,特此总结下: Intent与Bundle在传值上的区别 首先从使用上: Intent方式: 假设需要将数据从页面A传递到B,然后再传递到C. A页面中: Intent intent=

  • Android开发中Intent.Action各种常见的作用汇总

    本文介绍Android中Intent的各种常见作用. 1 Intent.ACTION_MAIN String: android.intent.action.MAIN 标识Activity为一个程序的开始.比较常用. Input:nothing Output:nothing <activity android:name=".Main" android:label="@string/app_name"> <intent-filter> <a

  • Android13 加强Intent filters 的安全性

    目录 Intent filters block non-matching intents 具体变更 豁免 适配办法 残留 Safer exporting of context-registered receivers 具体变更 豁免 适配办法 结语 前言: 在看这个变更之前,我们需要回忆下 Android 12 的一个安全性变更, 即声明了 <intent-filter> 的Activity.BroadcastReceiver.Service 必须声明 android:exported, 否则

  • 详解Android中Intent的使用方法

    一.Intent的用途 Intent主要有以下几种重要用途: 1. 启动Activity:可以将Intent对象传递给startActivity()方法或startActivityForResult()方法以启动一个Activity,该Intent对象包含了要启动的Activity的信息及其他必要的数据. 2. 启动Service:可以将Intent对象传递给startService()方法或bindService()方法以启动一个Service,该Intent对象包含了要启动的Service的

  • Android开发之Activity详解

    [Activity] 一个Activity是一个应用程序组件,提供一个屏幕,用户可以用来交互为了完成某项任务,例如拨号.拍照.发送email.看地图.每一个activity被给予一个窗口,在上面可以绘制用户接口.窗口通常充满屏幕,但也可以小于屏幕而浮于其它窗口之上. 一个应用程序通常由多个activities组成,他们通常是松耦合关系.通常,一个应用程序中的activity被指定为"main"activity,当第一次启动应用程序的时候呈现给用户的那个activity.每一个activ

  • Android App后台服务报告工作状态实例

    本节讲运行在后台服务里的工作请求,如何向发送请求者报告状态.推荐用LocalBroadcastManager发送和接收状态,它限制了只有本app才能接收到广播. 从IntentService汇报状态 从IntentService发送工作请求状态给其他组件,先创建一个包含状态和数据的Intent.也可以添加action和URI到intent里. 下一步,调用 LocalBroadcastManager.sendBroadcast()发送Intent,应用中所有注册了接收该广播的接收器都能收到.Lo

  • 浅析Android系统的架构以及程序项目的目录结构

    Android框架结构 直接上图: 由上图,我们可以看出Android系统架构由5部分组成, 分别是:Linux Kernel(linux内核).Android Runtime(运行时环境).Libraries(类库).Application Framework(应用框架).Applications(应用). 1.1.Linux Kernel Android基于Linux 2.6提供核心系统服务,例如:安全.内存管理.进程管理.网络堆栈.驱动模型.Linux Kernel也作为硬件和软件之间的抽

  • Android编程入门之HelloWorld项目目录结构分析

    本文实例讲述了Android编程入门之HelloWorld项目目录结构.分享给大家供大家参考,具体如下: 我们介绍了如何搭建Android开发环境及简单地建立一个HelloWorld项目,本篇将通过HelloWorld项目来介绍Android项目的目录结构.本文的主要主题如下: 1.HelloWorld项目的目录结构 1.1.src文件夹 1.2.gen文件夹 1.3.Android 2.1文件夹 1.4.assets 1.5.res文件夹 1.6.AndroidManifest.xml 1.7

  • Android编程简单实现拨号器功能的方法

    本文实例讲述了Android编程简单实现拨号器功能的方法.分享给大家供大家参考,具体如下: 学习Android已经有2天时间了,没学习的时候觉得android可能很枯燥,但是学过之后我发觉其实这个比什么javaweb好玩多了.学习android可以见到一些很有趣的东西,这里呢也建议学习javaME的人不要在煎熬了,学习android吧.在写程序之前也需要知道android的工作原理 1.获取组件清单 2.登记或注册组件 3.将组件封装成意图 4.把意图交给意图处理器进行处理 5.把界面显示给用户

  • Android中Textview超链接实现方式

    TextView中的超链接可以通过几种方式实现: 一.Html.fromHtml方式 TextView,本身就支持部分的Html格式标签.这其中包括常用的字体大小颜色设置,文本链接等.使用起来也比较方便,只需要使用Html类转换一下即可: textView.setText(Html.fromHtml(str)); 代码如下: public class Test10Activity extends Activity { TextView textView ; @Override protected

  • 解析Android声明和使用权限

    Android定义了一种权限方案来保护设备上的资源和功能.例如,在默认情况下,应用程序无法访问联系人列表.拨打电话等.下面就以拨打电话为例介绍一下系统对权限的要求.一般在我们的应用中,如果要用到拨打电话的功能,我们会这样编码: Uri uri = Uri.parse("tel:12345678"); Intent intent = new Intent(Intent.ACTION_CALL, uri); startActivity(intent); 默认情况下,我们无权访问拨打电话的A

  • Android中程序的停止状态详细介绍

    很多人遇到过广播收不到的问题,比如Google Play推广安装广播没有收到等,诸如这些问题,又都是什么原因呢,这篇文章将进行回答. 从Android 3.1(HoneyComb) 也就是API 12开始,Android引入了一套新的启动控制,这就是程序的停止状态.那让我们看一下Google对于程序的停止状态的描述. 什么是程序的停止状态 复制代码 代码如下: Starting from Android 3.1, the system's package manager keeps track

随机推荐