Android13 加强Intent filters 的安全性

2022-05-26 12:58:38
目录
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 intentsSafer exporting of context- -registered receivers

    Intent>

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

    在 13 以前:

      开发者想给 Component 添加 支持这个 需要公开给外部 App 使用,便设定了 Component exported 为 true这时候该 Component 就出现了一个安全漏洞:外部 App 使用不同于 中声明的 Action,甚至 mimeType 都不匹配均可以启动它

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

      具体变更

      假如我们提供了的>

      <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)
          }
      }

      豁免

      如下的几种场景下的>

        目标 Component 没有声明 <intent-filter>同一个 App 内部发出的 Intent系统发出的 Intent,包括 SystemServer、采用 System UID 的系统 AppRoot 进程发出的 Intent

        适配办法

        如果目标运行的版本基于>

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

          作为启动方:
            是否存在采用显式 Intent 方式启动其他 App 或发送广播的情况
              startActivity()startActivityForResult()sendBroadcast()该 Component 是否声明了 <intent-filter>防止其 Target 升级到了 Android 13 无法正常启动,需要注意 Intent 的 action、data 等信息是否准确作为目标方:
                Target 是否需要升级到 Android 13是否对外提供了 Component 并声明了 <intent-filter>防止无法被正常启动,需要告知启动方 <intent-filter> 的信息

                残留

                13>

                  startService()startForegroundService()bindService()

                  Safer>

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

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

                  具体变更

                  TargetSDK>

                  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

                    豁免

                    需要留意的是,系统级广播是受保护的,普通>

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

                    适配办法

                    找到所有动态注册>

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

                      结语

                      无论是针对>

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