Utilisateur:UNreaLIIR/Brouillon

Une page de Wikipédia, l'encyclopédie libre.

La popularité grandissante de la plate-formeAndroid en fait actuellement une cible privilégiée des derniers Malwares. Jusqu'alors pour améliorer la sécurité de la plate-forme et ainsi avoir un meilleur contrôle des données personnelles de l’utilisateur, il fallait passer par une modification importante du système d’exploitation, ce qui pose de réels problèmes de faisabilité pour un utilisateur lambda.

L’idée étant, dans un premier temps de pouvoir surveiller le comportement d’une application dans le détail de manière à pouvoir détecter des problèmes de sécurité et de violations de la vie privée. Parmi les failles potentielles, on retrouve les tentatives pour récupérer des informations sensibles, l'envoi de SMS secrètement à des numéros surtaxés, ou l'accès à des adresses IP malveillantes. Puis dans un second temps, de pouvoir appliquer des modifications précises sur ces applications de manière à pouvoir contrôler de manière très fine leur comportement et leur interactions, le tout sans modifier, ni altérer le système d’exploitation.

Introduction au problème[modifier | modifier le code]

Android est sans doute le système d’exploitation qui s’est répandu le plus rapidement dans le monde puisqu’il détient actuellement environ 75% du marché [1]. Cette croissance sans précédent en popularité, avec l'ouverture de son écosystème d'applications, a attiré de nombreuses entités malicieuses qui ont pris pour cible le système Android via des logiciels malveillants en tout genre. Ces logiciels malveillants ont généralement pour but d’accéder à des éléments de la vie privée de l’utilisateur voir même de prendre le contrôle total de l’appareil.

La lutte contre ces logiciels malveillants a pris trois directions principales. La première consiste en l'analyse statique et dynamique du code des applications de manière à détecter des comportements suspects avant que l’application ne soit chargée sur l'appareil de l’utilisateur. La seconde approche consiste à modifier le système d’exploitation Android pour pouvoir y insérer des modules de surveillances et ainsi permettre l’interception des activités suspectes des lors qu’elles se produisent sur l’appareil. La dernière approche consiste en l’utilisation de la virtualisation pour mettre en œuvre la séparation rigoureuse des domaines allant de l'isolement léger d'applications sur l'appareil, à l'exécution de plusieurs instances d' Android sur le même appareil.

Deux problèmes fondamentaux et étroitement liés viennent contrarier ces approches. Le premier étant que la notion de “comportement malveillant” est difficile à définir pour une application Android. L’accès à la vie privée et aux parties sensibles d' Android est contrôlé par une autorisation de l’utilisateur lors de l’installation de l’application. Les utilisateurs sont donc informés des données et des ressources auxquels l’application aura accès. Mais ces permissions n’empêchent pas de filtrer des actions précises car elles restent trop générales. Par exemple, une application peut légitimement exiger l'envoi de messages SMS. Mais une fois que l'autorisation SMS est accordée il n'y a pas de contrôles pour empêcher l'application d' envoyer des SMS à des numéros surtaxés sans le consentement de l'utilisateur.

Le deuxième problème est que toutes les approches jusqu'ici pour améliorer la sécurité et la confidentialité de la plate-forme Android sont basés sur une extensions de la politique qui nécessite une modification du système d'exploitation. Cela pose d’importants problèmes d'utilisabilité et entrave les efforts pour une adoption généralisée. Il existe de nombreuses tablettes et téléphones avec différentes configurations matérielles, chacun exécutant une version différente du système Android avec ses propres personnalisations et pilotes de périphériques. Ce phénomène, aussi appelé problème de la fragmentation des versions Android montre qu'il est difficile de fournir des versions personnalisées d’ Android pour tous les périphériques possibles à l'état sauvage. Il est encore plus difficile de demander à un utilisateur normal d'appliquer le patch source d'une certaine infrastructure de sécurité et de compiler Android pour son propre dispositif. Ces problèmes empêcheront de nombreux projet de sécurité pour le système d’exploitation Android d'être largement adoptée par les gens normaux.

Les failles[modifier | modifier le code]

Android est le système d’exploitation avec le système de communication inter application le plus sophistiqué. Le système Android a facilité le développement d’applications tierces, via l’accessibilité aux API, néanmoins par défaut une application n'a accès qu'à ses données et à un statut d’utilisateur avec peu de privilèges. Le système d’exploitation Android fournit aussi un riche système de communication entre les applications, malheureusement, c’est ce point qui rend les applications Android vulnérables car on peut intercepter, modifier, remplacer, détruire les messages qui circulent, et donc altérer la confidentialité des données des utilisateurs. Ainsi si un message ne définit pas clairement son destinataire ou son destinateur, c'est une faille potentiellement exploitable par les Malwares.

La communication inter-applications est une pratique courante, par exemple une application qui gère un restaurant peut afficher le site de ce restaurant en faisant appel à une autre application, un itinéraire jusqu’à ce restaurant sur une map toujours en utilisant une autre application… Tout cela dans le but d’optimiser la réutilisation des fonctionnalités, et donc faciliter le développement pour les développeurs. Cette pratique est un facteur de risque car elle utilise le système des intents pour fonctionner, qui s'il est mal paramétrer peut être une source non négligeable de piratage.

Les intents[modifier | modifier le code]

Un intent est un message qui déclare un récipient et optionnellement des données, il sert à la communication entre composants Android. Un intent est composé de 7 parties[2]:

  • Composant: Le nom de composant auquel est destiné l'intent en respectant le format "nom du package"."nom du composant"
  • Action: L'action à exécuter
  • Catégorie: Information supplémentaire sur l'action à effectuer et le type de de composant qui pourra gérer l'intent
  • Données: Il détermine le champ Type
  • Type: Le type des données incluse dans l'intent
  • Extras: Contenu ajouté à l'intent dans le but de le faire circuler entre composants
  • Flags: Permettent de modifier le comportement de l'intent

Il existe deux catégories d’intents :

  • Les explicites, qui spécifient le receveur du message via le champ Composant.
  • Les implicites, qui laissent le système déterminer quelle composant peut traiter le message. A noter qu'au minimum, les champs Action et Données doivent être remplis.

Il faut aussi signaler la hiérarchie de certains intents comme les System Broadcast Intents qui sont les intents qui ne peuvent être envoyés que depuis le système d’exploitation.Les intents peuvent être intra ou inter apllications.

Pour être capable de recevoir un intent, un composant doit obligatoirement être déclaré dans le fichier manifest[3], un broadcast peut lui aussi être déclaré dans ce fichier ou directement à l’exécution. Un composant peut recevoir des intents provenant d’autres applications s’il comporte la dénomination EXPORTED[4] ou s’il contient ou moins un intent filter, qui est un mécanisme servant à filtrer les intents que le composant accepte.

Les intents filters n’ont aucun mécanisme de protection. C’est-à-dire que n’importe qui peut appeler n’importe quelle action, type ou catégorie sur un composant (excepté les appels réservés au système). Il est aussi possible de contourner les intents filters en fournissant un intent explicit.

Les composants[modifier | modifier le code]

Une application Android se compose de plusieurs éléments appelés "Composants", ils sont classés en 4 types :

  • Activités: Elles fournissent les IHM et démarrent en recevant un intent, et peuvent retourner des données à son invocateur.
  • Services: Ils sont lancés en arrière-plan, ils n’interagissent pas avec l’utilisateur, ils démarrent et peuvent être liés à une méthode via un intent.
  • Broadcast Receivers: Ils existent juste le temps de relayer une information(Exemple: Signal de batterie faible). Il existe 3 types de Broadcasts Receivers :
    • Normal : Il est envoyé à tous les receveurs et disparaît ensuite.
    • Sticky : Il reste accessible après avoir transférer leur message pour de futurs receveurs.
    • Ordered : Il est communiqué un par un à chaque receveur, ainsi un receveur peut stopper sa propagation. De plus, les receveurs peuvent spécifier leur priorité.
  • Content Providers: Ils sont accessibles via leur URI, ils servent à stocker les données persistantes et permettent aussi de communiquer entre des applications.

Les intents ne peuvent s’adresser qu’aux Activités, Services et Broadcast Receivers. Par défaut, ces appels sont seulement internes à l’application.

Les Intents implicites[modifier | modifier le code]

Quand une application envoie un intent implicite, elle ne peut pas être sûre que celui-ci sera réceptionné par le destinataire désiré. Une application mal intentionnée pourrait déclarer un intent filter qui vérifie les caractéristiques de l’intent, et ainsi utiliser l’intent à sa guise mis à part si l’intent requiert des permissions que cette application mal intentionnée n’a pas.

Le vol via les Broadcast receivers:

  • Si un intent filter est crée et qu’il accepte tous les intents en définissant une liste de toutes les combinaisons possibles d’actions, données et catégories. Dans ce cas, les broadcast de type sticky sont accessibles du fait de leur existence sur le long terme. Les broadcasts de type ordered peuvent être stoppé par ce même programme. De plus, il n’y a aucun système d’accusé de réception pour les intents.

Activity Hijacking :

  • Ce système s’exécute via une activité qui va intercepter un intent implicite, récupérer les informations utiles et faire suivre l’intent à son destinataire d’origine. On pourrait facilement imaginer un intent appelant une activité servant à faire des donations qui serait intercepté, on pourrait alors détourner l’argent récolté. Ce principe et aussi valable pour le cas d’un Service Hijacking

Special Intents :

  • Pour accéder aux données du content provider d’une application le récepteur d’un intent doit en posséder les droits, ainsi dans la partie FLAGS de l’intent il faut ajouter les flags de ce genre :FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION. Si ce type d’intent est intercepté alors le programme pourra accéder à des données qui peuvent être sensibles.

Dalvik[modifier | modifier le code]

Android comporte une machine virtuelle nommée Dalvik, qui permet d'exécuter des programmes prévus pour la plate-forme Java. C'est une machine virtuelle conçue dès le départ pour les appareils mobiles et leurs ressources réduites - peu de puissance de calcul et peu de mémoire. La majorité, voire la totalité des applications sont exécutées par la machine virtuelle Dalvik. Le byte code de Dalvik est différent de celui de la machine virtuelle Java de Oracle (JVM), et le processus de construction d'une application est différent. le code source de l'application, en langage Java est tout d'abord compilé avec un compilateur standard qui produit du byte code pour JVM (byte code standard de la plate forme Java) puis ce dernier est traduit en byte code pour Dalvik par un programme inclus dans Android. Ce byte code pourra alors être exécuté.

Même si le l'architecture est différente, le niveau d'abstraction du byte code Dalvik est similaire à celui de la machine virtuelle Java. Les instructions dans le byte code Dalvik sont définie précisément par une spécification et peuvent donc être interprétées sans aucune ambiguïté.

Il existe plusieurs instructions pour les invocations de méthodes. Les instructions d'appel de méthode contiennent des informations précises telles que le type d'invocation (static, direct, virtual, super), la signature de la méthode, la classe parent, le nom de la méthode, le type de ses arguments ainsi que les registres associés à cet appel. Il est donc possible en analysant uniquement le byte code d'une application de comprendre son fonctionnement et aussi d'avoir accès à beaucoup d'informations sur le code source d'origine[5].

La structuration du byte code est donc très importante puisque l'on peut analyser le comportement d'une application sans avoir accès au code source, ce qui est fondamental si l'on souhaite modifier le comportement d'une application en ayant accès uniquement au byte code.

Détection de logiciels malveillants[modifier | modifier le code]

De nombreux antivirus dont le but est la détection de logiciels malveillants existent sur ordinateur mais leur propagation sur les smartphones ou tablettes est faible. En effet les utilisateurs de smartphone et tablettes ne semble pas encore sensibilisés aux menaces dont ils peuvent être la cible. Android permet l'installation d'applications tierces de manière très simple et il donc par conséquent très facile d'installer une application corrompue sans s'en rendre compte. Bien que les concepteurs du système Android ont pris en compte l'aspect sécurité, il ne faut pas pour autant se penser intouchable. Les logiciels antivirus sont donc indispensables si l'on veut éviter d’exécuter un programme infecté par mégarde.

Ces outils utilisent différentes techniques d'analyse pour détecter les logiciels malveillants lors de l'installation ou de l’exécution d'un programme. En effet il existent différents moyens de détection. On distingue deux philosophies principales. La première d'entre elles, dite par signature, consiste à chercher tous les comportements suspects en essayant de détecter la signature d'une attaque connue. La seconde approche cherche à établir une liste de comportement considérés comme normaux et à lever une alerte si l'on détecte un comportement qui ne fait pas partie de cette liste. Ces deux approches sont donc vraiment très différentes puisque d'un coté, pour la méthode par signature on a besoin de connaître le maximum de comportements suspects tandis que pour l'approche par anomalie on a besoin de connaître le maximum de comportements normaux. Ces deux approches sont donc complémentaire puisque la méthode par signature sera incapable de détecter une attaque zero-day alors que la méthode de détection d'anomalie aura quant à elle beaucoup de mal à détecter un programme malveillant dont le comportement est fortement similaire avec un programme normal.

Analyse statique et analyse dynamique[modifier | modifier le code]

L'analyse d'un programme peut être réalisée de deux manières différentes indépendamment de la technique de détection utilisée. En effet on distingue deux approches, l'analyse statique et l'analyse dynamique.

Une analyse statique se base uniquement sur le fichier binaire de l'application et la plupart des antivirus commerciaux utilise cette technique avec la méthode de détection par signature. Bien que cette technique soit très peu coûteuse en ressources, elle est tout de même très limitée face à des malwares inconnus. Les techniques d'analyses statiques standards, telles que l'analyse de type control-flow ou encore l'analyse de type data-flow peuvent être réalisées. Ce type d'analyses statiques permet d'avoir une vue globale et de nombreux chercheurs ont montrés que cette approche est très efficace dans de nombreux cas[6]. Cependant, les analyses statiques sont connues pour être vulnérables à certaines techniques telles que l’obfuscation de code qui est une technique commune dans le monde des malwares. De plus l'analyse statique permet difficilement d'établir un diagnostic sur un exploit puisque l'on a besoin d'un environnement d’exécution vulnérable pour observer et analyser un exploit et ainsi identifier la vulnérabilité[7].

L'analyse dynamique quant à elle utilise des informations collectés lors de l’exécution de l'application telles que les appels systèmes, les accès réseau ainsi que les écriture en mémoire etc... Cette technique nécessite donc de lancer l'application en mode sandbox afin de détecter des anomalies, ce qui nécessite beaucoup de ressources système et un peu de temps. Complémentairement à l'analyse statique, l'analyse dynamique est immunisée à l’offuscation de code et, est capable de détecter un comportement malveillant sur un chemin d’exécution. Son inconvénient est la couverture de code puisqu'elle ne s'intéresse qu'a un chemin d’exécution précis même si elle peut être améliorée en utilisant des chemins d’exécution multiples[8]. Malgré ses limitations l'analyse dynamique reste l'approche préférée parmi les chercheurs et les éditeurs de logiciels antivirus pour établir un profil du malware et extraire ses particularités. Mais le manque de façons automatisées d'explorer l'ensemble des possibilités est un facteur préjudiciable. Les techniques d'exploration de chemins d’exécutions multiples peuvent être utiles mais ne permettent pas d'avoir une vue globale[9].

Techniques utilisées en analyse statique[modifier | modifier le code]

En informatique l'analyse statique d'un programme rassemble de nombreuses méthodes permettant d'obtenir des informations précises sur le comportement d'un programme sans exécuter celui ci. Nous verrons deux méthodes d'analyse statique différentes souvent utilisées tout en sachant qu'il en existe d'autres.

Control Flow Analysis[modifier | modifier le code]

En informatique une analyse de controle de flots ou Control flow analysis fait référence à une analyse basée sur l'ordre dans lequel sont exécutés ou évalués des déclarations, instructions ou appels de fonctions.

Cette technique d'analyse statique se charge donc de déterminer le Control flow, ou flot de controle d'un programme.

Bien que pour la plupart des langages de programmation impératifs, l'ordre d’exécution d'un programme est explicite, ce type d'analyse est notamment utilisé pour déterminer le récepteur d'un appel de fonction. En effet dans des programmes écrit en langages de haut niveau, la cible d'un appel de fonction peut être implicite et cette technique d'analyse permet notamment de déterminer les cibles potentielles ainsi que les endroits dans lesquels cette expression pourrait être invoquée et quels arguments elle pourrait recevoir [10].

Data Flow Analysis[modifier | modifier le code]

L'analyse de flux de données, ou Data-flow analysis est une technique pour collecter de l'information à propos des ensembles de valeurs possibles calculés à différents points dans un programme. Pour cela, cette technique utilise le diagramme de contrôle de flot pour déterminer quelles parties du programme pour lequel l'attribution d'une valeur particulière à une variable peut se propager.

Une façon simple d'effectuer une analyse des flux de données de programmes est de mettre en place des équations de flux de données pour chaque nœud du graphe de flot de contrôle et de les résoudre plusieurs fois en calculant le résultat obtenu à partir de l'entrée locale à chaque nœud jusqu'à ce que l'ensemble du système se stabilise, c'est à dire, qu'il atteigne un point fixe [11].

Techniques utilisées en analyse dynamique[modifier | modifier le code]

Le but d'une analyse dynamique est de rechercher des indices pouvant montrer le comportement suspicieux d'un programme. Pour rechercher ces indices on se base sur les appels de méthodes, notamment en analysant les appels système puisque ils fournissent beaucoup d'informations sur le comportement d' un programme. Pour réaliser ces appels système, le programme doit demander au système d'exploitation d'effectuer cette action pour lui car si le programme se limite aux droits qui lui sont conférés il ne pourra pas réaliser toutes les actions qu'il souhaite. Une approche intéressante est donc d'intercepter ces appels pour les interpréter, le processus est nommé Hooking.

Le hooking est une technique utilisée en analyse dynamique qui permet d'observer quelle méthodes sont appelées par le programme et avec quels arguments. Pour cela il est nécessaire de récupérer les arguments stockés sur la pile au moment de l'appel de méthode. Dans le cas d'un fichier binaire à analyser, on peut une fois l'analyse terminée utiliser des méthodes de réécriture pour modifier le comportement du programme. On peut donc réécrire les méthodes que l'on souhaite surveiller, et faire appel à ces méthodes modifiées appelées méthodes de hook au moment de l’exécution du programme.

Une fois les données sur les appels de méthodes collectées, le détecteur doit être capable de les interpréter pour prendre la décision appropriée. Pour cela il existe encore une fois, deux approches différentes. La première est une approche statistique, la détecteur prend donc une décision en fonction du nombre et du type d'appels systèmes. La seconde approche consiste quant à elle a essayer des détecter des schémas en se basant sur les suites d'appels de méthodes. La méthode statistique nécessite une phase d'apprentissage puisque le détecteur doit avoir été entraîne sur des programmes dont le comportement est connu.

Notes et Références[modifier | modifier le code]

  1. (fr)[1] Parts de marché Android en 2013
  2. (fr)[2] Schéma d'un intent
  3. (en)[3] Definition du fchier manifest
  4. (en)[4] Exemple de fichier manifest pour une activité
  5. (en) [5] Section 2.2 Identifying Method Invocations
  6. (en)[6] A Study of Android Application Security, Section 4
  7. (en)[7] DroidScope: Seamlessly Reconstructing the OS and Dalvik Semantic Views for Dynamic Android Malware Analysis, Section 2.2 static analysis
  8. (en)[8] DroidScope: Seamlessly Reconstructing the OS and Dalvik Semantic Views for Dynamic Android Malware Analysis, Section 2.2 dynamic analysis
  9. (en)[9] Aurasium: Practical Policy Enforcement for Android Applications, Section 5 dynamic analysis
  10. (en)[10] Analyse de contrôle de flots
  11. (en)[11] Analyse de flot de données

Bibliographie[modifier | modifier le code]

  • (en) B. Davis, B. Sanders, A. Khodaverdian, H. Chen et M. Oestreiche, « A Rewriting Framework for In-App Reference Monitors for Android Applications[12] », http://mostconf.org/,‎
  • (en) H. Chu et P. Huang, « RetroSkeleton: retrofitting android apps[13] », http://www.cs.ucdavis.edu,‎
  • (en) K. Kennedy, E. Gustafson et H. Chen, « Quantifying the Effects of Removing Permissions from Android Applications[14] », http://www.mostconf.com/,‎
  • V. Turpaud, C. Talhi et L. Me, « Détection de logiciels malveillants sur Android[15] », http://www.irisa.fr/,‎
  • (en) J. Jeon, K. K. Micinski, J. A. Vaughan, A. Fogel, N. Reddy, J. S. Foster et T. Millstein, « Dr. Android and Mr. Hide: fine-grained permissions in android applications[16] », http://www.cs.ucla.edu/,‎
  • (en) J. Jeon, K. K. Micinski, J. A. Vaughan, A. Fogel, N. Reddy, J. S. Foster et T. Millstein, « Experimenting with system and Libc call interception attacks on ARM-based Linux kernel[17] », ACM,‎ , p. 631-632
  • (en) G. Portokalidis, P. Homburg, K. Anagnostakis et H. Bos, « Experimenting with system and Libc call interception attacks on ARM-based Linux kernel[18] », ACM,‎
  • (en) R. Xu, H. Saidi et R. Anderson, « Aurasium: Practical Policy Enforcement for Android Applications[19] », Proceedings of the 21st USENIX Security Symposium,‎
  • (en) E. Chin, A. Porter Felt, K. Greenwood et D. Wagner, « Analyzing inter-application communication in Android[20] », ACM,‎ , p. 239-252