Catégorie OWASP : MASVS-CODE : qualité du code
Présentation
Les risques associés aux autorisations personnalisées surviennent lorsque la définition des autorisations personnalisées est manquante ou mal orthographiée, ou lorsque l'attribut android:protectionLevel
correspondant est mal utilisé dans le fichier manifeste.
Par exemple, ces risques peuvent être exploités en créant une autorisation personnalisée portant le même nom, mais définie par une application malveillante et avec des niveaux de protection différents appliqués.
Les autorisations personnalisées sont conçues pour permettre de partager des ressources et des fonctionnalités avec d'autres applications. Voici quelques exemples d'utilisation légitime d'autorisations personnalisées:
- Contrôler la communication inter-processus (IPC) entre deux ou plusieurs applications
- Accéder à des services tiers
- Restreindre l'accès aux données partagées d'une application
Impact
Si vous exploitez cette faille, une application malveillante peut accéder aux ressources initialement prévues pour être protégées. Les conséquences de la faille dépendent de la ressource protégée et des autorisations associées au service d'application d'origine.
Risque: fautes de frappe dans les autorisations personnalisées
Une autorisation personnalisée peut être déclarée dans le fichier manifeste, mais une autre autorisation personnalisée est utilisée pour protéger les composants Android exportés, en raison d'une faute de frappe. Une application malveillante peut exploiter les applications qui ont mal orthographié une autorisation en:
- Enregistrer d'abord cette autorisation
- Anticiper l'orthographe dans les applications ultérieures
Cela peut permettre à une application d'accéder sans autorisation aux ressources ou de contrôler l'application victime.
Par exemple, une application vulnérable souhaite protéger un composant en utilisant une autorisation READ_CONTACTS
, mais fait accidentellement une erreur d'orthographe avec l'autorisation READ_CONACTS
. Une application malveillante peut revendiquer READ_CONACTS
, car elle n'appartient à aucune application (ni au système) et peut accéder au composant protégé. android:permission=True
est une autre variante courante de cette faille. Les valeurs telles que true
et false
, quelle que soit la casse, sont des entrées non valides pour la déclaration d'autorisation et sont traitées de la même manière que les autres fautes de frappe dans les déclarations d'autorisation personnalisées. Pour résoudre ce problème, remplacez la valeur de l'attribut android:permission
par une chaîne d'autorisation valide. Par exemple, si l'application doit accéder aux contacts de l'utilisateur, la valeur de l'attribut android:permission
doit être android.permission.READ_CONTACTS
.
Stratégies d'atténuation
Vérifications lint Android
Lorsque vous déclarez des autorisations personnalisées, utilisez les vérifications lint Android pour vous aider à trouver les fautes de frappe et d'autres erreurs potentielles dans votre code.
Convention d'attribution de noms
Utilisez une convention d'attribution de noms cohérente afin de rendre les fautes de frappe plus visibles. Vérifiez attentivement les déclarations d'autorisations personnalisées dans le fichier manifeste de votre application pour détecter les fautes de frappe.
Risque: autorisations orphelines
Les autorisations permettent de protéger les ressources des applications. Il existe deux emplacements différents dans lesquels une application peut déclarer les autorisations requises pour accéder aux ressources:
- AndroidManifest.xml: prédéfini dans le fichier AndroidManifest.xml (si non spécifié, les autorisations
<application>
sont utilisées), par exemple autorisation du fournisseur, autorisation du destinataire, autorisation d'activité, autorisation du service. - Code: enregistré dans le code d'exécution, par exemple
registerReceiver()
.
Cependant, il arrive que ces autorisations ne soient pas définies par une balise <permission>
correspondante dans le fichier manifeste d'un APK sur l'appareil. Dans ce cas, elles sont appelées autorisations orphelines. Cette situation peut se produire pour plusieurs raisons, par exemple:
- Il peut y avoir une désynchronisation entre les mises à jour du fichier manifeste et le code avec la vérification des autorisations.
- Il est possible que l'APK contenant les autorisations ne soit pas inclus dans le build ou qu'une version incorrecte soit incluse
- Le nom de l'autorisation dans la vérification ou dans le fichier manifeste peut être mal orthographié.
Une application malveillante peut définir une autorisation orpheline et l'acquérir. Dans ce cas, les applications privilégiées qui font confiance à l'autorisation orpheline pour protéger un composant peuvent être compromises.
Si l'application privilégiée utilise l'autorisation pour protéger ou restreindre un composant, cela peut accorder à l'application malveillante l'accès à ce composant. Par exemple, le lancement d'activités protégées par une autorisation, l'accès à un fournisseur de contenu ou la diffusion auprès d'un broadcast receiver protégé par l'autorisation orpheline.
Il peut également arriver que l'application privilégiée soit amenée à penser que l'application malveillante est une application légitime et qu'elle charge donc des fichiers ou du contenu.
Stratégies d'atténuation
Assurez-vous que toutes les autorisations personnalisées que votre application utilise pour protéger les composants sont également définies dans votre fichier manifeste.
L'application utilise les autorisations personnalisées my.app.provider.READ
et my.app.provider.WRITE
pour protéger l'accès à un fournisseur de contenu:
XML
<provider android:name="my.app.database.CommonContentProvider" android:readPermission="my.app.provider.READ" android:writePermission="my.app.provider.WRITE" android:exported="true" android:process=":myappservice" android:authorities="my.app.database.contentprovider"/>
L'application définit et utilise également ces autorisations personnalisées, ce qui empêche d'autres applications malveillantes de le faire:
XML
<permission android:name="my.app.provider.READ"/>
<permission android:name="my.app.provider.WRITE"/>
<uses-permission android:name="my.app.provider.READ" />
<uses-permission android:name="my.app.provider.WRITE" />
Risque: utilisation abusive d'android:protectionLevel
Cet attribut décrit le niveau de risque potentiel de l'autorisation et indique les procédures que le système doit suivre pour décider d'accorder ou non l'autorisation.
Stratégies d'atténuation
Éviter le niveau de protection normal ou dangereux
L'utilisation d'un protectionLevel
normal ou dangereux pour vos autorisations signifie que la plupart des applications peuvent demander et obtenir l'autorisation:
- "normal" ne nécessite que de le déclarer
- "dangereux" sera approuvé par de nombreux utilisateurs
Par conséquent, ces protectionLevels
offrent peu de sécurité.
Utiliser les autorisations de signature (Android 10 ou version ultérieure)
Utilisez les niveaux de protection de signature autant que possible. L'utilisation de cette fonctionnalité garantit que seules les autres applications signées avec le même certificat que l'application qui a créé l'autorisation peuvent accéder à ces fonctionnalités protégées. Assurez-vous d'utiliser un certificat de signature dédié (non réutilisé) et de le stocker de manière sécurisée dans un keystore.
Définissez une autorisation personnalisée comme suit dans votre fichier manifeste:
XML
<permission
android:name="my.custom.permission.MY_PERMISSION"
android:protectionLevel="signature"/>
Limitez l'accès à une activité, par exemple, uniquement aux applications qui disposent de cette autorisation personnalisée, comme suit:
XML
<activity android:name=".MyActivity" android:permission="my.custom.permission.MY_PERMISSION"/>
Toute autre application signée avec le même certificat que l'application qui a déclaré cette autorisation personnalisée se verra accorder l'accès à l'activité .MyActivity
et devra la déclarer comme suit dans son fichier manifeste:
XML
<uses-permission android:name="my.custom.permission.MY_PERMISSION" />
Attention aux autorisations personnalisées de signature (Android < 10)
Si votre application cible Android < 10, chaque fois que ses autorisations personnalisées sont supprimées en raison de désinstallations ou de mises à jour, des applications malveillantes peuvent toujours utiliser ces autorisations personnalisées et contourner ainsi les vérifications. Cela est dû à une faille d'escalade des privilèges (CVE-2019-2200
) qui a été corrigée dans Android 10.
C'est l'une des raisons (avec le risque de conditions de course) pour lesquelles les vérifications de signature sont recommandées par rapport aux autorisations personnalisées.
Risque: condition de concurrence
Si une A
d'application légitime définit une autorisation personnalisée de signature utilisée par d'autres applications X
, mais qu'elle est ensuite désinstallée, une application malveillante B
peut définir cette même autorisation personnalisée avec un protectionLevel
différent, par exemple normal. De cette manière, B
accède à tous les composants protégés par cette autorisation personnalisée dans les applications X
sans avoir à être signé avec le même certificat que l'application A
.
Il en va de même si B
est installé avant A
.
Stratégies d'atténuation
Si vous souhaitez qu'un composant ne soit disponible que pour les applications signées avec la même signature que celle qui fournit l'application, vous pourrez peut-être éviter de définir des autorisations personnalisées pour limiter l'accès à ce composant. Dans ce cas, vous pouvez utiliser des vérifications de signature. Lorsque l'une de vos applications envoie une requête pour une autre de vos applications, la seconde application peut vérifier que les deux applications sont signées avec le même certificat avant de répondre à la requête.
Ressources
- Réduire le nombre de demandes d'autorisation
- Présentation des autorisations
- Description des niveaux de protection
- CustomPermissionTypo Android Lint
- Utiliser Android Lint
- Article de recherche expliquant en détail les autorisations Android et présentant des résultats intéressants de tests de fuzz