粘性广播

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

概述

Android 应用和 Android 系统可以使用广播作为消息系统来通知其他应用它们可能感兴趣的事件。粘性广播是一种特殊的广播,其中发送的意图对象在广播完成之后仍保留在缓存中。系统可能会将粘性意图重新广播到接收器的后续注册。不幸的是,粘性广播 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包中的接收器在广播发送时接收意图。但是,当意图从粘性缓存中重新广播时,不会应用包名称过滤器。当使用registerReceiver()方法注册接收器时,粘性缓存中与指定过滤器匹配的所有意图都会重新广播到接收器,而不管接收器所在的包名称。

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

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

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

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

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

影响

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

缓解措施

不应使用粘性广播。推荐的方法是使用非粘性广播以及其他机制(例如本地数据库)来随时检索当前值。

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

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