SoFunction
Updated on 2025-03-11

Android13 enhances the security of Intent filters

Preface:

Before looking at this change, we need to recall a security change in Android 12, that is, we declare<intent-filter>The Activity, BroadcastReceiver, and Service must be declaredandroid:exported, otherwise it will not be activated.

This change to Android 12 is to prevent developers from declaring an intent-filter without knowing it, which will make these components public and enhance security to a certain extent.

But it's missingExplicit Intent StartandBroadcast Receiver Dynamic RegistrationIn both cases, two changes were introduced in 13 to strengthen them.

  • Intent filters block non- -matching intents
  • Safer exporting of context- -registered receivers

Intent filters block non-matching intents

Android 13 Start Intent Filters block mismatched intents, even if the explicit startup of Component is specified.

Before 13:

  • The developer wants to add support to Component
  • This needs to be exposed to external apps, so Component exported is set to true
  • At this time, a security vulnerability appeared in the Component: external apps can start it by using different Actions declared in , and even mimeType does not match

Maybe you don’t think this is anything but if the App only does a security check for the coming Route, it will cause omissions in verification.

Specific changes

If the Activity we provide is declared as follows:

<activity
    android:name=".MainActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="" />
        <category android:name="" />
    </intent-filter>
    <intent-filter>
        <action android:name="" />
        <data android:mimeType="/event"/>
    </intent-filter>
</activity>

Before 13, other apps adopted explicit startup, even if the wrong ACTION could start our activity normally.

private fun testIntentFilters() {
    Intent().setComponent(
        ComponentName("",
            "")
    ).apply {
        action = ".TEST_A"
        startActivity(this)
    }
}

If it runs on 13, it will not be started and the following error will occur:

PackageManager: Intent does not match component's intent filter: Intent { act=.TEST_A cmp=/.MainActivity }

PackageManager: Access blocked: ComponentInfo{/}

In addition to correct ACTION modification, data must also be started if it meets the Intent-filter fully meets it.

private fun testIntentFilters() {
    Intent().setComponent(
        ComponentName("",
            "")
    ).apply {
        action = ""
        data = .CONTENT_URI
        startActivity(this)
    }
}

Exemption

Intents in the following scenarios are not within the scope of the change:

  • Target Component is not declared<intent-filter>
  • Intents issued within the same app
  • The system's intents, includingSystemServer, System App using System UID
  • RootIntent issued by the process

Adaptation method

If the target run version is based on Android 13 and is not the exemption object mentioned above, some checks and necessary modifications are required.

Discussion on the adaptation method according to the two situations of the initiator and the target:

  • As the starter:
    • Is there any situation where other apps are started or broadcasts are sent using an explicit Intent method?
      • startActivity()
      • startActivityForResult()
      • sendBroadcast()
    • Is the Component declared?<intent-filter>
    • Prevent its Target from upgrading to Android 13 and fails to start normally. You need to pay attention to whether the Intent's action, data and other information are accurate.
  • As the target party:
    • Does Target need to be upgraded to Android 13
    • Whether the Component is provided to the outside world and declared<intent-filter>
    • To prevent it from being started normally, you need to inform the initiator.<intent-filter>Information

Remaining

13 The actual test on the above found that the Service component can be started normally even if it is an incorrect ACTION when it is explicitly started. Is this intentional or a beta version vulnerability? The source code has not been published yet, and the reason is unknown.

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

Safer exporting of context-registered receivers

To help improve the security of runtime receivers, Android 13 allows you to specify whether a specific broadcast receiver in your app should be exported and whether it is visible to other applications on the device.

If you export a broadcast receiver, other applications will be able to send unprotected broadcasts to your applications. This export configuration is available in applications targeting Android 13 or later, helping to prevent a major source of application vulnerabilities.

Specific changes

If the TargetSDK upgrade to Android13 app does not specify the flag when registering Receiver dynamically, you will receive the following crash:

: : One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts

Currently, the above restrictions do not take effect by default, and the following compatibility changes need to be enabled:

  • Developer Options -> App Compatibility Changes ->Your App -> DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED

In addition, when your Receiver declares RECEIVER_NOT_EXPORTED, other apps will fail to send broadcasts to it, and print the following log to remind your Receiver that it needs to be exposed:

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

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

Exemption

It should be noted that system-level broadcasting is protected and ordinary apps do not have permission to send.

So if you just listen to the system broadcast, the dynamically registered Receiver does not need to specify the above flag. Even if RECEIVER_NOT_EXPORTED is specified, it can be received normally and not affected by the same static registration method.

Adaptation method

Find all codes for dynamically registering Broadcast Receiver. If the listening includes non-system broadcasts, please add a flag statement based on whether it is exposed to other apps.

  • RECEIVER_EXPORTED
  • RECEIVER_NOT_EXPORTED
(sharedBroadcastReceiver, intentFilter,
    RECEIVER_EXPORTED)
(privateBroadcastReceiver, intentFilter,
    RECEIVER_NOT_EXPORTED)

Conclusion

Whether it is upgraded for Intent Fitler matching requirements or dynamically registered Receiver Flags, it is all about enhancing component security. I hope that developers will think more about these three components that they are used to and avoid loopholes.

This is the end of this article about Android13 strengthening the security of Intent filters. For more related content on Android Intent filters, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!