粘性广播

OWASP 类别: MASVS-PLATFORM:平台交互

概述

Android 应用和 Android 系统可以使用广播作为消息系统,以通知其他应用它们可能感兴趣的事件。粘性广播是一种特殊的广播,其中发送的 Intent 对象在广播完成后保留在缓存中。系统可能会将粘性 Intent 重新广播到接收器的后续注册。不幸的是,粘性广播 API 存在许多与安全相关的缺点,这就是为什么它在 Android 5.0(API 级别 21)中被弃用的原因。

任何人都可以访问粘性广播

粘性广播无法限制为拥有特定权限的接收器。因此,它们不适合广播敏感信息。您可能认为在广播 Intent 上指定 应用程序包名称 会限制 BroadcastReceivers 的集合

Kotlin

val intent = Intent("com.example.NOTIFY").apply {
    setPackage("com.example.myapp")
}
applicationContext.sendBroadcast(intent)

Java

Intent intent = new Intent("com.example.NOTIFY");
intent.setPackage("com.example.myapp");
getApplicationContext().sendBroadcast(intent);

在示例中,当发送广播时,只有 com.example.myapp 包中的接收器会收到 Intent。但是,当 Intent 从粘性缓存中重新广播时,不会应用包名称过滤器。当使用 registerReceiver() 方法注册接收器时,粘性缓存中与指定过滤器匹配的所有 Intent 都会重新广播到接收器,而不管接收器所在的包名称。

任何人都可以发送粘性广播

要发送粘性广播,应用只需要 android.permission.BROADCAST_STICKY 权限,该权限在安装应用时会自动授予。因此,攻击者可以将任何 Intent 发送到任何接收器,从而可能获得对另一个应用的未授权访问。广播接收器可以将发送方限制为拥有特定权限的发送方。但是,这样做后,接收器将无法接收来自粘性缓存的广播,因为这些广播不是在任何应用的身份上下文中发送的,并且不会使用任何权限广播。

任何人都可以修改粘性广播

当 Intent 是粘性广播的一部分时,该 Intent 会替换粘性缓存中具有相同操作、数据、类型、标识符、类和类别的任何先前实例。因此,攻击者可以轻松覆盖合法应用中粘性 Intent 的额外数据,然后将其重新广播到其他接收器。

使用sendStickyOrderedBroadcast() 方法发送的广播一次只发送到一个接收器,以允许优先级较高的接收器在广播发送到优先级较低的接收器之前先处理该广播。 每个接收器依次执行时,都可以将结果传播到下一个接收器,例如通过调用setResultData(),或者可以中止广播,阻止后续接收器接收广播。 攻击者如果可以从合法应用接收粘性有序广播,则可以创建一个高优先级接收器来篡改广播结果数据或完全丢弃广播。

影响

影响因粘性广播的使用方式和传递给广播接收器的数据而异。 一般来说,使用粘性广播可能导致敏感数据泄露、数据篡改、未经授权访问以在另一个应用中执行行为以及拒绝服务。

缓解措施

不应使用粘性广播。 建议的模式是使用非粘性广播以及其他机制(例如本地数据库),以便在需要时检索当前值。

开发人员可以使用权限或通过在意图上设置应用程序包名称来控制谁可以接收非粘性广播。 此外,如果广播不需要发送到应用外部的组件,请使用LiveData,它实现了观察者模式

有关广播安全性的更多信息,请参阅广播概述页面。