Catégorie OWASP : MASVS-CODE : qualité du code
Présentation
L'utilisation de PendingIntent.getCreator*()
ou PendingIntent.getTarget*()
pour déterminer s'il faut faire confiance à l'expéditeur d'un PendingIntent crée un risque d'exploitation.
PendingIntent.getCreator*()
ou PendingIntent.getTarget*()
renvoie le créateur de PendingIntent, qui ne correspond pas toujours à son expéditeur. Le créateur peut être digne de confiance, mais l'expéditeur ne doit jamais l'être, car il peut s'agir d'une application malveillante qui a acquis l'Intent en attente d'une autre application à l'aide de divers mécanismes, par exemple :
- de
NotificationListenerService
- cas d'utilisation légitimes qui font partie de l'application vulnérable.
Un exemple d'utilisation légitime de PendingIntent.getCreator*()
ou PendingIntent.getTarget*()
consiste à afficher l'icône de l'application qui sera lancée par PendingIntent.
Impact
Faire confiance à l'expéditeur d'une PendingIntent parce que vous avez interrogé (et faites confiance) au créateur peut entraîner des failles de sécurité. Si une application fait confiance à l'expéditeur de PendingIntent en fonction de son créateur, puis partage sa logique d'authentification ou d'autorisation, cela entraînerait un contournement de l'authentification ou potentiellement même une exécution de code à distance basée sur une entrée non valide et non fiable, chaque fois que l'expéditeur de PendingIntent est une application malveillante, en fonction de l'implémentation du code de l'application vulnérable.
Stratégies d'atténuation
Distinguer l'expéditeur du créateur
Tout type de logique d'authentification ou d'autorisation effectué lors de la réception d'une PendingIntent ne doit pas être basé sur des hypothèses concernant le créateur de la PendingIntent identifié à l'aide de PendingIntent.getCreator*()
ou PendingIntent.getTarget*()
.
Utiliser d'autres méthodes pour valider les appelants
Si vous devez authentifier l'appelant, au lieu d'utiliser PendingIntent, vous devez utiliser un service ou un ContentProvider. Les deux permettent de récupérer l'UID de l'appelant avec Binder.getCallingUid() lorsque vous êtes dans le contexte de l'envoi d'un IPC entrant. L'UID peut être interrogé ultérieurement à l'aide de PackageManager.getPackagesForUid().
Une autre approche, disponible à partir du niveau d'API 34, consiste à utiliser BroadcastReceiver.getSentFromUid() ou BroadcastReceiver.getSentFromPackage() si l'expéditeur a choisi de partager son identité lors de la diffusion à l'aide de BroadcastOptions.isShareIdentityEnabled().
Vous devez toujours vérifier si le package appelant possède la signature attendue, car les packages chargés de manière indépendante peuvent avoir des noms de package qui se chevauchent avec ceux du Play Store.