OWASP 类别: MASVS-CODE: 代码质量
概览
使用 PendingIntent.getCreator*()
或 PendingIntent.getTarget*()
来判断是否信任 PendingIntent 的发送方会产生利用风险。
PendingIntent.getCreator*()
或 PendingIntent.getTarget*()
返回 PendingIntent 的创建方,它并不总是与发送方匹配。创建方可能受到信任,但发送方永远不应受到信任,因为发送方可能是恶意应用,它通过各种机制获取了另一个应用的 PendingIntent,例如
- 来自
NotificationListenerService
- 作为受攻击应用的一部分的合法用例。
使用 PendingIntent.getCreator*()
或 PendingIntent.getTarget*()
的一个合法用例是显示将由 PendingIntent 启动的应用图标。
影响
信任 PendingIntent 的发送方(因为您查询并信任其创建方)可能会导致漏洞。如果应用基于 PendingIntent 的创建方信任其发送方,然后共享其身份验证或授权逻辑,那么当 PendingIntent 的发送方是恶意应用时,根据受攻击应用代码的实现方式,这可能会导致身份验证绕过,甚至可能基于无效的、不受信任的输入进行远程代码执行。
缓解措施
区分发送方和创建方
接收 PendingIntent 时执行的任何类型的身份验证或授权逻辑,都不得基于使用 PendingIntent.getCreator*()
或 PendingIntent.getTarget*()
识别出的 PendingIntent 创建方的假设。
使用其他方式验证调用方
如果您需要对调用方进行身份验证,则不应使用 PendingIntent,而应使用 Service 或 ContentProvider – 在分派传入 IPC 时,两者都允许通过 Binder.getCallingUid() 获取调用方的 UID。稍后可以使用 PackageManager.getPackagesForUid() 查询 UID。
另一种方法(自 API 级别 34 起可用)是,如果发送方在使用 BroadcastOptions.isShareIdentityEnabled() 进行广播期间选择了共享身份,则可以使用 BroadcastReceiver.getSentFromUid() 或 BroadcastReceiver.getSentFromPackage()。
您应始终检查调用方软件包是否具有预期的签名,因为通过侧载安装的软件包可能与 Play 商店中的软件包名称重叠。