39 KiB
Fondamentaux des applications Android
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Travaillez-vous dans une entreprise de cybersécurité ? Voulez-vous voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les PLANS D'ABONNEMENT !
- Découvrez The PEASS Family, notre collection exclusive de NFT
- Obtenez le swag officiel PEASS & HackTricks
- Rejoignez le 💬 groupe Discord ou le groupe Telegram ou suivez moi sur Twitter 🐦@carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR au repo hacktricks et au repo hacktricks-cloud.
Trouvez les vulnérabilités les plus importantes afin de les corriger plus rapidement. Intruder suit votre surface d'attaque, effectue des analyses de menace proactives et trouve des problèmes dans l'ensemble de votre pile technologique, des API aux applications web et aux systèmes cloud. Essayez-le gratuitement dès 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 isole les applications installées les unes des autres.
- L'application elle-même, qui permet aux développeurs de exposer certaines fonctionnalités et de configurer les capacités de l'application.
Séparation des UID
Chaque application se voit attribuer un ID 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 ID utilisateur ou les fichiers partagés. Par conséquent, seule l'application elle-même, certains composants du système d'exploitation et l'utilisateur root peuvent accéder aux données des applications.
Partage des 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'entre elles est compromise, les données des deux applications seront compromises. C'est pourquoi ce comportement est déconseillé.
Pour partager le même UID, les applications doivent définir la même valeur android:sharedUserId
dans leurs manifestes.
Isolation
Le bac à sable des applications Android permet d'exécuter chaque application en tant que processus distinct sous un ID utilisateur distinct. Chaque processus a sa propre machine virtuelle, de sorte que le code d'une application s'exécute de manière isolée par rapport aux autres applications.
À partir d'Android 5.0(L), SELinux est appliqué. Fondamentalement, SELinux refuse toutes les interactions entre les processus, puis crée des politiques pour autoriser uniquement les interactions attendues entre eux.
Autorisations
Lorsque vous installez une application et qu'elle demande des autorisations, l'application demande les autorisations configurées dans les éléments uses-permission
du fichier AndroidManifest.xml. L'élément uses-permission indique le nom de l'autorisation demandée dans l'attribut name. Il a également l'attribut maxSdkVersion qui arrête de demander des autorisations sur les versions supérieures à celle spécifiée.
Notez que les applications Android n'ont pas besoin de demander toutes les autorisations au début, elles peuvent également demander des autorisations dynamiquement, mais toutes les autorisations doivent être déclarées dans le manifeste.
Lorsqu'une application expose des fonctionnalités, elle peut limiter l'accès uniquement aux applications qui ont une autorisation spécifiée.
Un élément d'autorisation a trois attributs :
- Le nom de l'autorisation
- L'attribut permission-group, qui permet de regrouper les autorisations connexes.
- Le niveau de protection qui indique comment les autorisations 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 tenu d'approuver.
- Dangerous : Indique que l'autorisation accorde à l'application demandant un accès accru. 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 l'autorisation. Il s'agit du type de protection le plus fort.
- SignatureOrSystem : Seules les applications signées par le même certificat que celui exportant le composant ou les applications s'exécutant avec un accès de niveau système peuvent se voir accorder des autorisations.
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
). Il vaut la peine de vérifier ces applications car parfois elles s'exécutent avec trop de permissions (en tant que root).
- Celles livrées avec le ROM de l'AOSP (Android OpenSource Project)
- Ajoutées par le fabricant de l'appareil
- Ajoutées par le fournisseur de téléphonie mobile (si acheté chez eux)
Rootage
Pour obtenir un accès root sur un appareil Android physique, vous avez généralement besoin d'exploiter 1 ou 2 vulnérabilités qui sont généralement spécifiques à l'appareil et à la version.
Une fois que l'exploit a fonctionné, 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 que le binaire su est 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 rootage 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é. En faisant cela, il est possible d'étendre l'utilité d'un ancien appareil, contourner les restrictions logicielles ou accéder au code Android le plus récent.
OmniROM et LineageOS sont deux des firmwares les plus populaires à utiliser.
Notez que ce n'est pas toujours nécessaire de rooter l'appareil pour installer un firmware personnalisé. Certains fabricants permettent le déverrouillage de leurs chargeurs d'amorçage de manière bien documentée et sécurisée.
Implications
Une fois qu'un appareil est rooté, n'importe quelle application peut demander l'accès en tant que root. Si une application malveillante l'obtient, elle pourra avoir 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 l'ouvrir et voir son contenu.)
- Contenu de l'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 se trouve ici !
- classes.dex
- Le 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 de l'application se trouvent ici par défaut ! Sous le répertoire lib/, il y a les répertoires spécifiques au processeur.
armeabi
: code compilé pour tous les processeurs ARM uniquementarmeabi-v7a
: code compilé pour tous les processeurs ARMv7 et supérieurs uniquementx86
: code compilé pour X86mips
: code compilé pour les processeurs MIPS uniquement- 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 notamment lorsque les auteurs de logiciels malveillants veulent essayer de "cacher" du code supplémentaire, natif ou Dalvik, en ne l'incluant pas aux emplacements par défaut.
- res/
- Le répertoire contenant les 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 parle de "Java", vous pouvez supposer que je veux dire "Java ou Kotlin". Au lieu que le code Java s'exécute dans une machine virtuelle Java (JVM) comme les applications de bureau, dans Android, le Java est compilé en bytecode _Dalvik Executable (DEX)_* format**. Pour les versions antérieures d'Android, le bytecode était traduit par la machine virtuelle Dalvik. Pour les versions plus récentes d'Android, l'Android Runtime (ART) est utilisé.
Si les développeurs écrivent en Java et que le code est compilé en bytecode DEX, pour effectuer une rétro-ingénierie, nous travaillons dans la direction opposée.
\
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 en Android, nous utilisons souvent le terme "Smali" pour désigner les instructions. Si vous avez déjà 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 plus haut niveau et le bytecode.
Trouvez les vulnérabilités les plus importantes afin de pouvoir les corriger plus rapidement. Intruder suit votre surface d'attaque, effectue des analyses de menace 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 dès 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 à la façon dont les requêtes GET/POST sont utilisées dans les communications HTTP.
Ainsi, 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 simplifier, un Intent peut être utilisé :
- Pour démarrer une activité, ouvrir une interface utilisateur pour une application
- Comme des 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 des ContentProviders
- Comme des rappels pour gérer des événements
Une implémentation incorrecte peut entraîner une fuite de données, l'appel de fonctions restreintes et la manipulation du flux de programme.
Filtre d'Intent
Un filtre d'Intent spécifie les types d'Intent auxquels une activité, un service ou un récepteur de diffusion peut répondre. Il spécifie ce qu'une activité ou un service peut faire et quels types de diffusions un récepteur peut gérer. Il permet au composant correspondant de recevoir des Intents du type déclaré. Les filtres d'Intent sont généralement définis via le fichier AndroidManifest.xml. Pour un récepteur de diffusion, il est également possible de les définir dans le code. Un filtre d'Intent est défini par sa catégorie, ses actions et ses filtres de données. Il peut également contenir des métadonnées supplémentaires.
Dans Android, une activité/service/fournisseur de contenu/récepteur de diffusion est public lorsque exported
est défini sur true
, mais un composant est également public si le manifeste spécifie un filtre d'Intent pour celui-ci. Cependant,
les développeurs peuvent rendre explicitement les composants privés (indépendamment de tout filtre d'Intent)
en définissant 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 d'accès au composant, limitant ainsi l'accès à celui-ci.
Intentions implicites
Les intentions sont créées de manière programmatique à l'aide d'un constructeur Intent :
Intent email = new Intent(Intent.ACTION_SEND, Uri.parse("mailto:"));
L'Action de l'intent précédemment déclaré est ACTION_SEND et l'Extra est un Uri mailto (l'Extra est l'information supplémentaire que l'intent attend).
Cet intent doit être déclaré 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 de l'intention" détermine quelle application doit 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
. En cas de conflit, une fenêtre "choisir" apparaît pour que l'utilisateur puisse décider.
Intents explicites
Un intent explicite spécifie le nom de la classe qu'il vise :
Intent downloadIntent = new (this, DownloadService.class):
Dans d'autres applications, pour accéder à l'intention précédemment déclarée, 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 de prendre des actions au nom de votre application, en utilisant l'identité et les permissions de votre application. Pour construire une intention en attente, il faut spécifier une intention et l'action à effectuer. Si l'intention déclarée n'est pas explicite (ne déclare pas quelle intention peut l'appeler), une application malveillante pourrait effectuer l'action déclarée au nom de l'application victime. De plus, si aucune action n'est spécifiée, l'application malveillante pourra effectuer 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 API 14, il est possible de spécifier l'application qui doit recevoir le message en utilisant Intent.setPackage.
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 supprimer la diffusion.
Il est possible d'envoyer une diffusion en utilisant la fonction **sendBroadcast(intent, receiverPermission)
** de la classe Context
.
Vous pouvez également utiliser la fonction sendBroadcast
de LocalBroadCastManager
qui garantit 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.
Celles-ci ont été dépréciées à partir du niveau API 21 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 "persistant" 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 l'appareil Android essaie d'accéder à une adresse en utilisant ce schéma, l'activité de l'application sera appelée :
Dans ce cas, le schéma est myapp://
(notez également la catégorie BROWSABLE
)
Si vous trouvez quelque chose comme ceci dans le intent-filter
:
Alors, il attend quelque chose comme http://www.example.com/gizmos
Si vous trouvez quelque chose comme ceci :
Cela signifiera qu'il attend une URL commençant par example://gizmos
Dans ce cas, vous pouvez essayer d'exploiter la fonctionnalité en créant un site web avec les charges utiles suivantes. Cela essaiera de naviguer vers des pages arbitraires et d'exécuter du code 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 deeplinks sans utiliser de pages HTML.
AIDL - Android Interface Definition Language
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 une 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 marquer les objets de part et d'autre de cette frontière pour vous. Le code pour effectuer cette marquage est fastidieux à écrire, c'est pourquoi 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 ici que commence l'interaction, c'est donc 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 (comme les activités) de se lier au service, d'envoyer des requêtes, 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 d'application et ne s'exécute pas indéfiniment en arrière-plan.
Messenger
Un Messenger est un autre type de mécanisme IPC. Étant donné que le Messenger est également un "service lié", les données transmises depuis l'application cliente sont également traitées par la méthode onBind
. Ainsi, l'examen du code devrait commencer par cette méthode et vous devriez rechercher l'invocation de fonctionnalités sensibles ou une manipulation non sécurisée des données.
Binder
Il est rare de trouver une classe Binder invoquée directement 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 vers celle d'un autre (https://www.youtube.com/watch?v=O-UHvFjxwZ8).
Composants
Ces composants comprennent : 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, c'est-à-dire une 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 lorsque l'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 répertoriées.
Gardez à l'esprit que toutes les applications n'auront pas une activité de lancement, en particulier les applications sans interface utilisateur. Des exemples d'applications sans interface utilisateur (et donc sans activité de lancement) sont les applications préinstallées qui fournissent des services en arrière-plan, tels que 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, ce qui permet à 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ès.
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 transmises en paramètre de l'Intent. Si ce sont des données sensibles, vous pourriez avoir une vulnérabilité de fuite d'informations et elle peut être exploitée 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 n'ont pas besoin de définir une sous-classe personnalisée de Application. Si une application Android définit une sous-classe de Application, cette classe est instanciée avant toute autre classe de l'application.
Si la méthode attachBaseContext
est définie dans la sous-classe de Application, elle est appelée en premier, avant la méthode onCreate
.
Services
Les services s'exécutent en arrière-plan sans interface utilisateur. Ils sont utilisés pour effectuer des processus longs, même si l'utilisateur commence à utiliser une autre application.
Il existe une multitude de façons de les démarrer et ils constituent donc un point d'entrée pour les applications. La façon par défaut de démarrer un service en tant que point d'entrée d'une application est par le biais d'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. Elle s'exécutera indéfiniment jusqu'à ce que la méthode stopService
soit appelée. Si le service n'est nécessaire que tant que le client est connecté, le client doit s'y "lier" en utilisant la méthode bindService
.
Pour un service lié (voir la section précédente), les données seront transmises à la méthode onBind
.
Par exemple, un service peut jouer de la musique en arrière-plan pendant que l'utilisateur se trouve dans une autre application, ou il peut récupérer des données via 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 Manifeste :
<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 façons pour une application de s'enregistrer en tant que récepteur : dans le manifeste de l'application ou enregistré dynamiquement dans le code de l'application en utilisant l'appel d'API registerReceiver
. Dans le manifeste, vous pouvez limiter les diffusions que vous acceptez en utilisant des autorisations dans l'élément récepteur. Lorsqu'il est défini dynamiquement, vous pouvez transmettre l'autorisation à 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 doivent déclencher le récepteur.
Lorsque les diffusions spécifiques pour lesquelles le récepteur est enregistré sont envoyées, la méthode onReceive
de la classe BroadcastReceiver est exécutée.
Une application peut par exemple s'enregistrer en tant que récepteur pour le message de batterie faible et modifier 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 prioritaire 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 supprimer l'intention reçue ou même la modifier en utilisant l'une des méthodes setter. Par conséquent, les récepteurs doivent valider les données.
Fournisseur de contenu
Les fournisseurs de contenu sont la façon dont les applications partagent des données structurées, telles que des bases de données relationnelles. Il est donc très important d'utiliser des autorisations 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 les autorisations qu'une application doit avoir. Ces autorisations ont la priorité sur l'attribut d'autorisation. De plus, ils peuvent également autoriser des exceptions temporaires en définissant grantUriPermission
sur true, puis en configurant les paramètres appropriés dans l'élément grant-uri-permission
à l'intérieur de l'élément fournisseur du fichier manifeste.
grant-uri-permission
a trois attributs : path, pathPrefix et pathPattern :
- path : permet de spécifier le chemin complet à exclure
- pathPrefix : permet de spécifier le début du chemin
- pathPattern : permet d'utiliser des caractères génériques et des remplacements symboliques pour un contrôle plus granulaire.
Il est important de valider et de nettoyer les entrées reçues pour éviter les vulnérabilités potentielles telles que les injections 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 accessible par votre application.
- 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 permet de partager des fichiers à partir d'un dossier. Vous pouvez déclarer un fournisseur de fichiers de la manière suivante :
<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 des dossiers que ce FileProvider va partager. Voici un exemple de comment indiquer le partage d'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 existe une autre vulnérabilité dans une partie du code qui tente d'accéder à ce fournisseur.
Vous pouvez accéder à une image à l'intérieur de 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, consultez ici.
Plus d'informations sur les FileProviders ici.
WebViews
Les WebViews sont en fait des navigateurs Web intégrés aux 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 tous les navigateurs Web. Cependant, il existe certaines configurations qui peuvent être utiles pour limiter la surface d'attaque.
Il existe deux types de WebViews sur Android :
- Le WebViewClient, le mieux adapté pour le rendu simple du HTML. Cela n'exécutera pas la fonction d'alerte JS. Ainsi, les tests XSS utilisant cette fonction seront invalides.
- Le client WebChrome, 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 aux URL sanitaires.
La sécurité des WebView peut être configurée via l'objet WebSettings
.
Par exemple, l'exécution du code JS peut être désactivée en utilisant la méthode setJavaScriptEnabled
avec la valeur false
. Cela supprimera la possibilité d'une XSS et d'autres vulnérabilités liées à JS.
La fonctionnalité JavaScript "Bridge" 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 pour la 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 les URL file://, mais il existe plusieurs façons d'empêcher ce comportement :
- Passer
false
àsetAllowFileAccess
, empêche l'accès au système de fichiers à l'exception des ressources viafile:///android_asset
etfile:///android_res
. Ces chemins ne doivent être utilisés que pour des données non sensibles (comme des images), donc cela devrait être sûr. - La méthode
setAllowFileAccess
indique si un chemin à partir d'une URLfile://
doit pouvoir accéder au contenu d'autres URL de schéma de fichier. - La méthode
setAllowUniversalAccessFromFileURLs
indique si un chemin à partir d'une URLfile://
doit pouvoir accéder au contenu de n'importe quelle origine.
Autres composants d'application
Signature d'application
- Android exige que toutes les applications soient signées numériquement avec un certificat avant de pouvoir être installées. Android utilise ce certificat pour identifier l'auteur d'une application.
- Pour exécuter une application sur l'appareil, elle doit être signée. Lorsqu'une application est installée sur un appareil, le gestionnaire de packages vérifie si l'application a été correctement signée avec le certificat du fichier APK ou non.
- L'application peut être auto-signée ou signée par une autorité de certification.
- La signature de l'application garantit qu'une application ne peut pas accéder à une autre application sauf par le biais d'IPC bien définis et qu'elle est transmise sans modification à l'appareil.
Vérification d'application
- Android 4.2 et versions ultérieures prennent en charge la vérification d'application. Les utilisateurs peuvent choisir d'activer la fonctionnalité "Vérifier les applications" et faire évaluer les applications par un vérificateur d'applications avant l'installation.
- La vérification de l'application peut avertir l'utilisateur s'il essaie d'installer une application potentiellement dangereuse ; 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 un contrôle et des exigences de sécurité sur les appareils mobiles. Ces suites utilisent les fonctionnalités appelées API d'administration de périphérique et nécessitent l'installation d'une application Android.
Généralement, les solutions MDM effectuent des fonctions telles que l'application de politiques de mot de passe, le chiffrement forcé du stockage et la possibilité d'effacer à distance les données de l'appareil.
Trouvez les vulnérabilités les plus importantes afin de pouvoir les corriger plus rapidement. Intruder suit votre surface d'attaque, effectue des analyses de menaces proactives, trouve des problèmes dans toute votre pile technologique, des API aux applications Web et aux systèmes cloud. Essayez-le gratuitement dès aujourd'hui.
{% embed url="https://www.intruder.io/?utm_campaign=hacktricks&utm_source=referral" %}
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- Vous travaillez dans une entreprise de cybersécurité ? Vous voulez voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les PLANS D'ABONNEMENT !
- Découvrez The PEASS Family, notre collection exclusive de NFTs
- Obtenez le swag officiel PEASS & HackTricks
- Rejoignez le 💬 groupe Discord ou le groupe Telegram ou suivez moi sur Twitter 🐦@carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR au repo hacktricks et au repo hacktricks-cloud.