待处理 intent 的发送者

OWASP 类别:MASVS-CODE:代码质量

概览

使用 PendingIntent.getCreator*()PendingIntent.getTarget*() 来确定是否信任 PendingIntent 的发送方会带来被利用的风险。

PendingIntent.getCreator*()PendingIntent.getTarget*() 会返回 PendingIntent 的创建者,但该创建者并不总是与其发送者一致。创建者可能值得信任,但发送者绝不值得信任,因为发送者可能是恶意应用,它通过各种机制获取了另一个应用的 PendingIntent,例如:

PendingIntent.getCreator*()PendingIntent.getTarget*() 的合法使用示例是显示将由 PendingIntent 启动的应用的图标。

影响

由于您查询(并信任)了创建者,因此信任 PendingIntent 的发送者可能会导致出现漏洞。如果应用基于 PendingIntent 的创建者信任其发送者,然后共享其身份验证或授权逻辑,那么每当 PendingIntent 的发送者是恶意应用时,就会导致身份验证绕过,甚至可能基于无效的、不受信任的输入执行远程代码,具体取决于易受攻击的应用代码的实现。

缓解措施

区分发送者和创作者

接收 PendingIntent 时执行的任何类型的身份验证或授权逻辑都不得基于以下假设:PendingIntent 的创建者是使用 PendingIntent.getCreator*()PendingIntent.getTarget*() 标识的。

使用其他方式验证调用方

如果您需要对调用方进行身份验证,则应使用 Service 或 ContentProvider,而不是 PendingIntent。当您处于调度传入 IPC 的上下文中时,这两者都允许使用 Binder.getCallingUid() 获取调用方 UID。稍后可以使用 PackageManager.getPackagesForUid() 查询 UID。

另一种方法(从 API 级别 34 开始提供)是使用 BroadcastReceiver.getSentFromUid()BroadcastReceiver.getSentFromPackage()(如果发送方选择在广播期间使用 BroadcastOptions.isShareIdentityEnabled() 共享身份)。

您应始终检查调用方软件包是否具有预期签名,因为旁加载的软件包的软件包名称可能与 Play 商店中的软件包名称重叠。

资源