hacktricks/mobile-pentesting/android-app-pentesting/android-applications-basics.md

38 KiB

Notions de base sur les applications Android

Apprenez le hacking AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!

Autres moyens de soutenir HackTricks :

Trouvez les vulnérabilités les plus importantes pour les corriger plus rapidement. Intruder suit votre surface d'attaque, effectue des scans de menaces proactifs, trouve des problèmes dans l'ensemble de votre pile technologique, des API aux applications web et aux systèmes cloud. Essayez-le gratuitement aujourd'hui.

{% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %}


Modèle de sécurité Android

Il y a deux couches :

  • Le système d'exploitation, qui maintient les applications installées isolées les unes des autres.
  • L'application elle-même, qui permet aux développeurs d'exposer certaines fonctionnalités et configure les capacités de l'application.

Séparation UID

Chaque application se voit attribuer un identifiant utilisateur spécifique. Cela est fait lors de l'installation de l'application afin que l'application ne puisse interagir qu'avec les fichiers appartenant à son identifiant utilisateur ou avec des fichiers partagés. Par conséquent, seuls l'application elle-même, certains composants du système d'exploitation et l'utilisateur root peuvent accéder aux données de l'application.

Partage UID

Deux applications peuvent être configurées pour utiliser le même UID. Cela peut être utile pour partager des informations, mais si l'une d'elles est compromise, les données des deux applications seront compromises. C'est pourquoi ce comportement est découragé.
Pour partager le même UID, les applications doivent définir la même valeur android:sharedUserId dans leurs manifestes.

Sandbox

Le bac à sable des applications Android permet d'exécuter chaque application comme un processus séparé sous un identifiant utilisateur séparé. Chaque processus a sa propre machine virtuelle, donc le code d'une application s'exécute isolément des autres applications.
À partir d'Android 5.0(L) SELinux est appliqué. En gros, SELinux a refusé toutes les interactions entre processus, puis a créé des politiques pour autoriser uniquement les interactions attendues entre eux.

Permissions

Lorsque vous installez une application et qu'elle demande des permissions, l'application demande les permissions configurées dans les éléments uses-permission du fichier AndroidManifest.xml. L'élément uses-permission indique le nom de la permission demandée dans l'attribut name. Il a également l'attribut maxSdkVersion qui arrête de demander des permissions pour les versions supérieures à celle spécifiée.
Notez que les applications Android n'ont pas besoin de demander toutes les permissions au début, elles peuvent également demander des permissions de manière dynamique mais toutes les permissions doivent être déclarées dans le manifeste.

Lorsqu'une application expose des fonctionnalités, elle peut limiter l'accès uniquement aux applications disposant d'une permission spécifiée.
Un élément de permission a trois attributs :

  • Le nom de la permission
  • L'attribut permission-group, qui permet de regrouper des permissions connexes.
  • Le niveau de protection qui indique comment les permissions sont accordées. Il existe quatre types :
    • Normal : Utilisé lorsqu'il n'y a aucune menace connue pour l'application. L'utilisateur n'est pas obligé de l'approuver.
    • Dangereux : Indique que la permission accorde à l'application demandant une accessibilité élevée. Les utilisateurs sont invités à les approuver.
    • Signature : Seules les applications signées par le même certificat que celui exportant le composant peuvent se voir accorder la permission. C'est le type de protection le plus fort.
    • SignatureOuSystème : Seules les applications signées par le même certificat que celui exportant le composant ou les applications fonctionnant avec un accès au niveau du système peuvent se voir accorder des permissions

Applications préinstallées

Ces applications se trouvent généralement dans les répertoires /system/app ou /system/priv-app et certaines d'entre elles sont optimisées (vous ne trouverez peut-être même pas le fichier classes.dex). Ces applications méritent d'être vérifiées car parfois elles fonctionnent avec trop de permissions (en tant que root).

  • Celles livrées avec la ROM AOSP (Projet OpenSource Android)
  • Ajoutées par le fabricant de l'appareil
  • Ajoutées par le fournisseur de téléphonie mobile (si achetées chez eux)

Rooting

Pour obtenir un accès root sur un appareil Android physique, vous devez généralement exploiter 1 ou 2 vulnérabilités qui sont généralement spécifiques à l'appareil et à la version.
Une fois l'exploit réussi, généralement le binaire Linux su est copié dans un emplacement spécifié dans la variable d'environnement PATH de l'utilisateur comme /system/xbin.

Une fois le binaire su configuré, une autre application Android est utilisée pour interagir avec le binaire su et traiter les demandes d'accès root comme Superuser et SuperSU (disponibles dans le Google Play Store).

{% hint style="danger" %} Notez que le processus de rooting est très dangereux et peut endommager gravement l'appareil {% endhint %}

ROMs

Il est possible de remplacer le système d'exploitation en installant un firmware personnalisé. Cela permet d'étendre l'utilité d'un ancien appareil, de contourner les restrictions logicielles ou d'accéder au dernier code Android.
OmniROM et LineageOS sont deux des firmwares les plus populaires à utiliser.

Notez que il n'est pas toujours nécessaire de rooter l'appareil pour installer un firmware personnalisé. Certains fabricants permettent le déverrouillage de leurs chargeurs de démarrage de manière bien documentée et sûre.

Implications

Une fois qu'un appareil est rooté, n'importe quelle application peut demander un accès root. Si une application malveillante l'obtient, elle aura accès à presque tout et pourra endommager le téléphone.

Fondamentaux des applications Android

Cette introduction est tirée de https://maddiestone.github.io/AndroidAppRE/app_fundamentals.html

Révision des fondamentaux

  • Les applications Android sont au format de fichier APK. APK est essentiellement un fichier ZIP. (Vous pouvez renommer l'extension du fichier en .zip et utiliser unzip pour ouvrir et voir son contenu.)
  • Contenu APK (Non exhaustif)
    • AndroidManifest.xml
    • resources.arsc/strings.xml
    • resources.arsc : un fichier contenant des ressources précompilées, telles que du XML binaire par exemple.
    • res/xml/files_paths.xml
    • META-INF/
      • Le certificat vit ici !
    • classes.dex
      • Bytecode Dalvik pour l'application au format de fichier DEX. C'est le code Java (ou Kotlin) compilé que l'application exécutera par défaut.
    • lib/
      • Les bibliothèques natives pour l'application, par défaut, se trouvent ici ! Sous le répertoire lib/, il y a les répertoires spécifiques au processeur.
      • armeabi : code compilé uniquement pour tous les processeurs basés sur ARM
      • armeabi-v7a : code compilé uniquement pour tous les processeurs basés sur ARMv7 et supérieurs
      • x86 : code compilé pour X86
      • mips : code compilé uniquement pour les processeurs MIPS
    • assets/
      • Tout autre fichier pouvant être nécessaire à l'application.
      • Des bibliothèques natives supplémentaires ou des fichiers DEX peuvent être inclus ici. Cela peut se produire surtout lorsque les auteurs de logiciels malveillants veulent essayer de "cacher" du code supplémentaire, natif ou Dalvik, en ne l'incluant pas dans les emplacements par défaut.
    • res/
      • le répertoire contenant des ressources non compilées dans resources.arsc

Dalvik & Smali

La plupart des applications Android sont écrites en Java. Kotlin est également pris en charge et interopérable avec Java. Pour simplifier, pour le reste de cet atelier, lorsque je fais référence à "Java", vous pouvez supposer que je veux dire "Java ou Kotlin". Au lieu que le code Java soit exécuté dans la machine virtuelle Java (JVM) comme les applications de bureau, sur Android, le Java est compilé au format de bytecode _Dalvik Executable (DEX)_. Pour les versions antérieures d'Android, le bytecode était traduit par la machine virtuelle Dalvik. Pour les versions plus récentes d'Android, le Runtime Android (ART) est utilisé.
Si les développeurs écrivent en Java et que le code est compilé en bytecode DEX, pour la rétro-ingénierie, nous travaillons dans la direction opposée.
\

Organigramme du processus du développeur. Java en bytecode DEX

Organigramme du processus de l'ingénieur inverse. Bytecode DEX en SMALI en Java décompilé

Smali est la version lisible par l'homme du bytecode Dalvik. Techniquement, Smali et baksmali sont les noms des outils (assembleur et désassembleur, respectivement), mais dans Android, nous utilisons souvent le terme "Smali" pour faire référence aux instructions. Si vous avez fait de la rétro-ingénierie ou de l'architecture informatique sur du code C/C++ compilé. SMALI est comme le langage d'assemblage : entre le code source de haut niveau et le bytecode.

Trouvez les vulnérabilités les plus importantes pour les corriger plus rapidement. Intruder suit votre surface d'attaque, effectue des scans de menaces proactifs, trouve des problèmes dans l'ensemble de votre pile technologique, des API aux applications web et aux systèmes cloud. Essayez-le gratuitement aujourd'hui.

{% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %}


Intents

Les Intents sont le principal moyen par lequel les applications Android communiquent entre leurs composants ou avec d'autres applications. Ces objets de message peuvent également transporter des données entre les applications ou les composants, de manière similaire à l'utilisation des requêtes GET/POST dans les communications HTTP.

Donc, un Intent est essentiellement un message qui est transmis entre les composants. Les Intents peuvent être dirigés vers des composants ou des applications spécifiques, ou peuvent être envoyés sans destinataire spécifique.
Pour être simple, Intent peut être utilisé :

  • Pour démarrer une Activité, ouvrant généralement une interface utilisateur pour une application
  • Comme diffusions pour informer le système et les applications des changements
  • Pour démarrer, arrêter et communiquer avec un service en arrière-plan
  • Pour accéder aux données via les ContentProviders
  • Comme callbacks pour gérer les événements

Une mise en œuvre incorrecte pourrait entraîner une fuite de données, l'appel de fonctions restreintes et la manipulation du flux du programme.

Intent-Filter

Un filtre d'intention spécifie les types d'Intent auxquels une activité, un service ou un Broadcast Receiver peut répondre. Il spécifie ce qu'une activité ou un service peut faire et quels types de diffusions un Receiver peut gérer. Il permet au composant correspondant de recevoir des Intents du type déclaré. Les filtres d'intention sont généralement définis via le fichier AndroidManifest.xml. Pour un Broadcast Receiver, il est également possible de les définir dans le code. Un filtre d'intention est défini par sa catégorie, son action et ses filtres de données. Il peut également contenir des métadonnées supplémentaires.

Dans Android, une activité/service/content provider/broadcast receiver est public lorsque exported est réglé sur true, mais un composant est également public si le manifeste spécifie un filtre d'intention pour celui-ci. Cependant,
les développeurs peuvent explicitement rendre les composants privés (indépendamment de tout filtre d'intention)
en réglant l'attribut exported sur false pour chaque composant dans le fichier manifeste.
Les développeurs peuvent également définir l'attribut permission pour exiger une certaine permission pour accéder au composant, limitant ainsi l'accès au composant.

Intentions implicites

Les Intents sont créés programmatiquement en utilisant un constructeur Intent :

Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));

L'Action de l'intention précédemment déclarée est ACTION_SEND et l'Extra est un Uri mailto (l'Extra est l'information supplémentaire que l'intention attend).

Cette intention doit être déclarée dans le manifeste comme dans l'exemple suivant :

<activity android:name="ShareActivity">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>

Un intent-filter doit correspondre à l'action, aux données et à la catégorie pour recevoir un message.

Le processus de "Résolution d'intent" détermine quelle application devrait recevoir chaque message. Ce processus prend en compte l'attribut de priorité, qui peut être défini dans la déclaration de l'intent-filter, et celui avec la priorité la plus élevée sera sélectionné. Cette priorité peut être définie entre -1000 et 1000 et les applications peuvent utiliser la valeur SYSTEM_HIGH_PRIORITY. Si un conflit survient, une fenêtre de "choix" apparaît pour que l'utilisateur puisse décider.

Intents explicites

Un intent explicite spécifie le nom de la classe qu'il cible :

Intent downloadIntent = new (this, DownloadService.class):

Dans d'autres applications, pour accéder à l'intent précédemment déclaré, vous pouvez utiliser :

Intent intent = new Intent();
intent.setClassName("com.other.app", "com.other.app.ServiceName");
context.startService(intent);

Intentions en attente

Celles-ci permettent à d'autres applications d'agir au nom de votre application, en utilisant l'identité et les permissions de votre app. Lors de la construction d'une Intention en attente, il faut spécifier une intention et l'action à réaliser. Si l'intention déclarée n'est pas Explicite (ne déclare pas quelle intention peut l'appeler), une application malveillante pourrait réaliser l'action déclarée au nom de l'application victime. De plus, si une action n'est pas spécifiée, l'application malveillante pourra faire n'importe quelle action au nom de la victime.

Intentions de diffusion

Contrairement aux intentions précédentes, qui ne sont reçues que par une seule application, les intentions de diffusion peuvent être reçues par plusieurs applications. Cependant, à partir de la version 14 de l'API, il est possible de spécifier l'application qui devrait recevoir le message en utilisant Intent.set Package.

Il est également possible de spécifier une permission lors de l'envoi de la diffusion. L'application réceptrice devra avoir cette permission.

Il existe deux types de diffusions : Normales (asynchrones) et Ordonnées (synchrones). L'ordre est basé sur la priorité configurée dans l'élément récepteur. Chaque application peut traiter, relayer ou abandonner la diffusion.

Il est possible d'envoyer une diffusion en utilisant la fonction sendBroadcast(intent, receiverPermission) de la classe Context.
Vous pourriez également utiliser la fonction sendBroadcast du LocalBroadCastManager qui assure que le message ne quitte jamais l'application. En utilisant cela, vous n'aurez même pas besoin d'exporter un composant récepteur.

Diffusions persistantes

Ce type de diffusions peut être accédé longtemps après leur envoi.
Elles ont été dépréciées dans la version 21 de l'API et il est recommandé de ne pas les utiliser.
Elles permettent à n'importe quelle application de renifler les données, mais aussi de les modifier.

Si vous trouvez des fonctions contenant le mot "sticky" comme sendStickyBroadcast ou sendStickyBroadcastAsUser, vérifiez l'impact et essayez de les supprimer.

Liens profonds / Schémas d'URL

Les liens profonds permettent de déclencher une Intention via une URL. Une application peut déclarer un schéma d'URL à l'intérieur d'une activité de sorte que chaque fois que le dispositif Android tente d'accéder à une adresse utilisant ce schéma, l'activité de l'application sera appelée :

Dans ce cas, le schéma est myapp:// (notez aussi la catégorie BROWSABLE)

Si à l'intérieur du intent-filter vous trouvez quelque chose comme ceci :

Alors, il s'attend à quelque chose comme http://www.example.com/gizmos

Si vous trouvez quelque chose comme ceci :

Cela signifiera qu'il s'attend à une URL commençant par example://gizmos
Dans ce cas, vous pourriez essayer d'abuser de la fonctionnalité en créant un web avec les charges utiles suivantes. Il essaiera de naviguer vers des pages arbitraires et d'essayer d'exécuter du JS :

<a href="example://gizmos/https://google.com">click here</a>
<a href="example://gizmos/javascript://%250dalert(1)">click here</a>

Pour trouver le code qui sera exécuté dans l'application, allez à l'activité appelée par le deeplink et recherchez la fonction onNewIntent.

Apprenez comment appeler des deep links sans utiliser de pages HTML.

AIDL - Langage de Définition d'Interface Android

Le Langage de Définition d'Interface Android (AIDL) vous permet de définir l'interface de programmation sur laquelle le client et le service s'accordent pour communiquer entre eux en utilisant la communication interprocessus (IPC). Sur Android, un processus ne peut normalement pas accéder à la mémoire d'un autre processus. Ainsi, pour communiquer, ils doivent décomposer leurs objets en primitives que le système d'exploitation peut comprendre, et transférer les objets à travers cette limite pour vous. Le code pour faire ce transfert est fastidieux à écrire, donc Android le gère pour vous avec AIDL.

Les services utilisant AIDL sont appelés Services Liés. Dans la classe du Service, vous trouverez la méthode onBind. C'est là que l'interaction commence, donc c'est la première partie du code à examiner à la recherche de vulnérabilités potentielles.

Un service lié est le serveur dans une interface client-serveur. Il permet aux composants (tels que les activités) de se lier au service, d'envoyer des demandes, de recevoir des réponses et d'effectuer une communication interprocessus (IPC). Un service lié vit généralement seulement tant qu'il sert un autre composant de l'application et ne fonctionne pas indéfiniment en arrière-plan.

Messenger

Un Messenger est un autre type de mécanisme IPC. Comme le Messenger est également un "Service Lié", les données transmises par l'application cliente sont également traitées via la méthode onBind. Ainsi, la revue de code devrait commencer par cette méthode et vous devriez rechercher l'invocation de fonctionnalités sensibles ou la gestion non sécurisée des données.

Binder

Il est rare de trouver une classe Binder directement invoquée car il est beaucoup plus facile d'utiliser AIDL (qui abstrait la classe Binder). Cependant, il est bon de savoir que Binder est un pilote de niveau noyau qui déplace les données de la mémoire d'un processus à celle d'un autre (https://www.youtube.com/watch?v=O-UHvFjxwZ8).

Composants

Cela inclut : Activités, Services, Récepteurs de Diffusion et Fournisseurs.

Activité de Lancement et autres activités

Une activité Android est un écran de l'interface utilisateur de l'application Android. De cette manière, une activité Android est très similaire aux fenêtres d'une application de bureau. Une application Android peut contenir une ou plusieurs activités, signifiant un ou plusieurs écrans.

L'activité de lancement est ce que la plupart des gens considèrent comme le point d'entrée d'une application Android. L'activité de lancement est l'activité qui est démarrée lorsqu'un utilisateur clique sur l'icône d'une application. Vous pouvez déterminer l'activité de lancement en regardant le manifeste de l'application. L'activité de lancement aura les intentions MAIN et LAUNCHER suivantes listées.

Gardez à l'esprit que toutes les applications n'auront pas une activité de lancement, en particulier les applications sans UI. Des exemples d'applications sans UI (et donc sans activité de lancement) sont les applications préinstallées qui effectuent des services en arrière-plan, comme la messagerie vocale.

<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

Les activités peuvent être exportées, permettant à d'autres processus sur l'appareil de lancer l'activité. Par défaut, elles ne sont pas exportées, mais vous pouvez les exporter en définissant :

<service android:name=".ExampleExportedService" android:exported="true"/>

Notez que la capacité à contourner les protections d'activité n'est pas toujours une vulnérabilité, vous devez vérifier à quelles données vous avez accédé. De plus, certaines activités renvoient des données à l'appelant. Dans ces scénarios, vous devez rechercher la méthode setResult et vérifier les données qui sont passées dans le paramètre Intent. Si c'est des données sensibles, vous pourriez avoir une vulnérabilité de fuite d'informations et c'est exploitable avec des applications capables de communiquer avec l'Activité.

Le code d'une activité commence par la méthode onCreate.

Sous-classe d'Application

Les applications Android peuvent définir une sous-classe de Application. Les applications peuvent, mais ne sont pas obligées de définir une sous-classe personnalisée d'Application. Si une application Android définit une sous-classe d'Application, cette classe est instanciée avant toute autre classe dans l'application.

Si la méthode attachBaseContext est définie dans la sous-classe d'Application, elle est appelée en premier, avant la méthode onCreate.

Services

Les Services fonctionnent en arrière-plan sans interface utilisateur. Ils sont utilisés pour effectuer des processus de longue durée, même si l'utilisateur commence à utiliser une autre application.

Il existe une myriade de façons dont ils peuvent être démarrés et sont donc un point d'entrée pour les applications. La manière par défaut qu'un service peut être démarré comme point d'entrée d'une application est à travers les Intents.

Lorsque la méthode startService est appelée pour démarrer un Service, la méthode onStart dans le Service est exécutée. Il fonctionnera indéfiniment jusqu'à ce que la méthode stopService soit appelée. Si le service est seulement nécessaire tant que le client est connecté, le client doit se "lier" à celui-ci en utilisant la méthode bindService.

Pour un service lié (voir section précédente), les données seront passées à la méthode onBind.

Par exemple, un service peut jouer de la musique en arrière-plan pendant que l'utilisateur est dans une autre application, ou il peut récupérer des données sur le réseau sans bloquer l'interaction de l'utilisateur avec une activité.

Un service peut être exporté ce qui permet à d'autres processus sur l'appareil de démarrer le service. Par défaut, les services ne sont pas exportés mais cela peut être configuré dans le Manifest :

<service android:name=".ExampleExportedService" android:exported="true"/>

Récepteurs de diffusion

Les diffusions peuvent être considérées comme un système de messagerie et les récepteurs de diffusion sont les auditeurs. Si une application a enregistré un récepteur pour une diffusion spécifique, le code de ce récepteur est exécuté lorsque le système envoie la diffusion. Notez que dans ce cas plusieurs applications peuvent recevoir le même message.

Il existe 2 manières pour une application de enregistrer un récepteur : dans le Manifest de l'application ou enregistré dynamiquement dans le code de l'application en utilisant l'appel API registerReceiver. Dans le manifeste, vous pouvez limiter les diffusions que vous acceptez grâce à l'utilisation de permissions dans l'élément récepteur. Lorsqu'il est défini dynamiquement, vous pouvez passer la permission à la méthode registerReceiver.

Dans les deux cas, pour enregistrer le récepteur, les filtres d'intention pour le récepteur sont définis. Ces filtres d'intention sont les diffusions qui devraient déclencher le récepteur.

Lorsque les diffusions spécifiques pour lesquelles le récepteur est enregistré sont envoyées, onReceive dans la classe BroadcastReceiver est exécuté.

Une application peut enregistrer un récepteur pour le message de batterie faible par exemple, et changer son comportement en fonction de cette information.

La diffusion peut être asynchrone (chaque récepteur la reçoit) ou synchrone (la diffusion est reçue de manière ordonnée en fonction de la priorité définie pour la recevoir).

{% hint style="danger" %} Notez que n'importe quelle application peut se définir comme priorité maximale pour recevoir une Diffusion. {% endhint %}

Pour examiner le code implémenté dans un Récepteur de diffusion, vous devez rechercher la méthode onReceive de la classe du récepteur.
Notez que les Diffusions Ordonnées peuvent abandonner l'Intent reçu ou même le modifier en utilisant l'une des méthodes setter. Par conséquent, les récepteurs devraient valider les données.

Fournisseur de contenu

Les Fournisseurs de contenu sont la manière dont les applications partagent des données structurées, telles que des bases de données relationnelles. Par conséquent, il est très important d'utiliser des permissions et de définir le niveau de protection approprié pour les protéger.
Les Fournisseurs de contenu peuvent utiliser les attributs readPermission et writePermission pour spécifier quelles permissions une application doit avoir. Ces permissions prévalent sur l'attribut permission.
De plus, ils peuvent également autoriser des exceptions temporaires en définissant grantUriPermission sur vrai, puis en configurant les paramètres appropriés dans l'élément grant-uri-permission à l'intérieur de l'élément fournisseur dans le fichier manifeste.

L'attribut grant-uri-permission a trois attributs : path, pathPrefix et pathPattern :

  • path : Permet de spécifier l'intégralité du chemin à exclure
  • pathPrefix : Permet de spécifier le début du chemin
  • pathPattern : Permet l'utilisation de jokers et de remplacements symboliques pour un contrôle plus granulaire.

Il est important de valider et d'assainir les entrées reçues pour éviter d'éventuelles vulnérabilités comme l'injection SQL.

Caractéristiques du Fournisseur de contenu :

  • Le composant Fournisseur de contenu fournit des données d'une application à d'autres sur demande.
  • Vous pouvez stocker les données dans le système de fichiers, une base de données SQLite, sur le web ou tout autre emplacement de stockage persistant auquel votre application peut accéder.
  • Grâce au fournisseur de contenu, d'autres applications peuvent interroger ou même modifier les données (si le fournisseur de contenu le permet).
  • Le Fournisseur de contenu est utile dans les cas où une application souhaite partager des données avec une autre application.
  • Il est très similaire aux bases de données et dispose de quatre méthodes.
  • insert()
  • update()
  • delete()
  • query()

FileProvider

Il s'agit d'un type de Fournisseur de contenu qui va partager des fichiers à partir d'un dossier. Vous pouvez déclarer un fournisseur de fichiers comme ceci :

<provider android:name="androidx.core.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true" android:exported="false">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>

Notez l'attribut android:exported car s'il est true, les applications externes pourront accéder aux dossiers partagés.
Notez que la configuration android:resource="@xml/filepaths" indique que le fichier res/xml/filepaths.xml contient la configuration de quels dossiers ce FileProvider va partager. Voici un exemple de comment indiquer de partager un dossier dans ce fichier :

<paths>
<files-path path="images/" name="myimages" />
</paths>

Partager quelque chose comme path="." pourrait être dangereux même si le fournisseur n'est pas exporté s'il y a une autre vulnérabilité dans une partie du code qui a tenté d'accéder à ce fournisseur.
Vous pourriez accéder à une image dans ce dossier avec content://com.example.myapp.fileprovider/myimages/default_image.jpg

L'élément <paths> peut avoir plusieurs enfants, chacun spécifiant un répertoire différent à partager. En plus de l'élément <files-path>, vous pouvez utiliser l'élément <external-path> pour partager des répertoires dans le stockage externe, et l'élément <cache-path> pour partager des répertoires dans votre répertoire de cache interne.
Pour plus d'informations sur les attributs spécifiques des fournisseurs de fichiers, cliquez ici.

Plus d'informations sur les FileProviders ici.

WebViews

Les WebViews sont essentiellement des navigateurs web intégrés dans les applications Android.
Le contenu des WebViews peut être extrait de sites distants ou peut être des fichiers inclus dans l'application.
Les WebViews sont vulnérables aux mêmes vulnérabilités affectant tout navigateur web. Cependant, il existe certaines configurations qui peuvent être utiles pour limiter la surface d'attaque.

Il existe deux types de WebViews sous Android :

  • Le WebViewClient, mieux adapté pour le rendu de HTML simple. Cette fonction ne lancera pas la fonction d'alerte JS. Ainsi, les tests XSS utilisant cette fonction seront invalides.
  • Le WebChrome client, est un navigateur Chrome.

Notez que les navigateurs WebView n'ont pas accès aux cookies du navigateur natif.

Pour charger une URL ou un fichier, il est possible d'utiliser les fonctions loadUrl, loadData ou loadDataWithBaseURL. Il est important d'accéder uniquement à des URL assainies.
La sécurité des WebView peut être configurée via l'objet WebSettings.
Par exemple, l'exécution de code JS peut être désactivée en utilisant la méthode setJavaScriptEnabled avec la valeur false. Cela éliminera la possibilité d'un XSS et d'autres vulnérabilités liées à JS.

La fonctionnalité "Bridge" JavaScript injecte des objets Java dans un WebView les rendant accessibles à JS. À partir d'Android 4.2, les méthodes doivent être annotées avec @JavascriptInterface pour être accessibles à JavaScript.

Si true est passé à setAllowContentAccess, les WebViews pourront accéder aux fournisseurs de contenu via le schéma content://. Cela pose évidemment un risque de sécurité. Notez que si cet accès est accordé, il est très important de s'assurer que l'URL content:// est sûre.

Par défaut, les fichiers locaux peuvent être accessibles par les WebViews via des URL file://, mais il existe plusieurs moyens de prévenir ce comportement :

  • Passer false à setAllowFileAccess, empêche l'accès au système de fichiers à l'exception des actifs via file:///android_asset et file:///android_res. Ces chemins devraient être utilisés uniquement pour des données non sensibles (comme des images), donc cela devrait être sûr.
  • La méthode setAllowFileAccess indique si un chemin d'une URL file:// devrait pouvoir accéder au contenu d'autres URL de schéma de fichier.
  • La méthode setAllowUniversalAccessFromFileURLs indique si un chemin d'une URL file:// devrait pouvoir accéder au contenu de n'importe quelle origine.

Autres composants d'application

Signature d'application

  • Android exige que toutes les applications soient numériquement signées avec un certificat avant qu'elles puissent être installées. Android utilise ce certificat pour identifier l'auteur d'une application.
  • Pour exécuter l'application sur l'appareil, elle doit être signée. Lorsqu'une application est installée sur un appareil, le gestionnaire de paquets vérifie si l'application a été correctement signée avec le certificat dans le fichier apk ou non.
  • L'application peut être auto-signée ou signée par une CA.
  • La signature d'application garantit qu'une application ne peut pas accéder à une autre application sauf par le biais d'IPC bien défini et aussi qu'elle est transmise sans modification à l'appareil.

Vérification d'application

  • Android 4.2 et les versions ultérieures prennent en charge la vérification des applications. Les utilisateurs peuvent choisir d'activer la vérification des applications "Verify Apps" et faire évaluer les applications par un vérificateur d'applications avant l'installation.
  • La vérification des applications peut alerter l'utilisateur s'il essaie d'installer une application qui pourrait être nuisible ; si une application est particulièrement mauvaise, elle peut bloquer l'installation.

Gestion des appareils mobiles

MDM ou Mobile Device Management sont des suites logicielles utilisées pour assurer le contrôle et les exigences de sécurité sur les appareils mobiles. Ces suites utilisent les fonctionnalités appelées API d'administration de l'appareil et nécessitent qu'une application Android soit installée.

Généralement, les solutions MDM effectuent des fonctions telles que l'application de politiques de mot de passe, le forçage du chiffrement du stockage et l'activation de l'effacement à distance des données de l'appareil.

Trouvez les vulnérabilités qui comptent le plus afin de les corriger plus rapidement. Intruder suit votre surface d'attaque, effectue des analyses de menaces proactives, trouve des problèmes dans l'ensemble de votre pile technologique, des API aux applications web et aux systèmes cloud. Essayez-le gratuitement aujourd'hui.

{% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %}


Apprenez le hacking AWS de zéro à héros avec htARTE (HackTricks AWS Red Team Expert)!

Autres moyens de soutenir HackTricks :