Transfert de données sécurisé entre deux applications

Bonjour à tous, aujourd'hui, je voudrais vous parler de certaines options de transfert de données entre deux applications Android et les considérer d'un point de vue de la sécurité. J'ai décidé d'écrire cet article pour deux raisons. Tout d'abord, j'ai souvent commencé à rencontrer un manque de compréhension des développeurs des mécanismes de travail avec les composants d'une application Android. La seconde - j'ai cessé de comprendre sur quoi se fonde le choix de tel ou tel mécanisme lors de l'implémentation des fonctionnalités et je voulais transmettre à quoi il devrait ressembler au minimum.

Défi

Nous avons 2 applications qui accèdent à la même API. Les clients peuvent accéder à l'API par jeton d'accès (sessionId). Vous devez implémenter une transition transparente d'une application à une autre. Pour ce faire, vous devez tâtonner entre eux, par exemple, que ce soit sessionId.

Option n ° 1: QUERY DEEPLINK

L'option la plus évidente consiste à transférer le jeton vers Query DeepLink. Cela ressemblera à ceci:
slave://main?sessionId=686A885A4FB644053C584B9BE2A70C7D
Dans ce cas, le destinataire pourra extraire sessionId et l'utiliser sans demander l'autorisation de l'utilisateur. Du côté du développeur, il semble que la tâche soit terminée, mais creusons un peu plus.

Détournement de lien profond


Étant donné que toute application peut enregistrer le schéma tinkoff: //, le système d'exploitation peut ouvrir la mauvaise application. Cela est possible du fait qu'il n'y a pas d'enregistrement et de restrictions sur l'utilisation des programmes. Une application malveillante peut enregistrer le schéma tinkoff: // et intercepter la demande vers l'application Tinkoff et démarrer elle-même. Dans ce cas, sessionId tombera entre de mauvaises mains et votre compte sera compromis. De plus, DeepLink Hijacking vous permet d'effectuer du phishing, par exemple, en affichant des champs pour entrer un nom d'utilisateur et un mot de passe.

Conceptuellement, le processus ressemble à ceci:

image

Il existe 2 solutions à ce problème. Premièrement, la technologie AppLinks ne permet plus aux développeurs de personnaliser le schéma; à la place, http / https est utilisé. Dans ce cas, le système d'exploitation prend le lien slave.com/profile et contacte l'hôte slave.com pour vérification. La seconde - URL d'intention - au lieu d'appeler slave: //, l'intention: // est appelée, où l'identifiant unique de l'application à lancer est transmis. Cela ressemble à ceci:

 intent://main/#Intent;scheme=slave;package=com.example.slave.client.android;end" 

Dans ce cas, il ne sera pas possible d'intercepter le lancement de l'application, car un package spécifique est spécifié. Pourtant, le problème demeure que l'utilisateur peut installer l'application à partir d'une source tierce avec le même packageId que votre esclave. Dans ce cas, si vous ne disposiez pas d'une application esclave légitime, l'application malveillante installera et recevra votre jeton.

Fixation de session


Il s'agit d'une attaque dans laquelle un attaquant force le client à établir une session avec le logiciel cible à l'aide de l'identifiant de session fourni par l'attaquant. Dès que l'utilisateur s'authentifie, l'attaquant pourra utiliser cet identifiant déjà privilégié à ses propres fins. L'attaque exploite le fait que le logiciel cible utilise le même sessionId après une élévation de privilèges.


À quoi cela ressemble dans notre cas:

  1. l'attaquant obtient une session anonyme de l'application
  2. jette magnifiquement une lettre à la victime au nom de la banque, dans laquelle il est invité à se rendre sur son compte personnel
  3. en cliquant sur le lien, on accède à DeepLink avec un attaquant session esclave: // main? sessionId = 686A885A4FB644053C584B9BE2A70C7D
  4. l'application mobile prend une session, comprend qu'elle ne dispose pas de droits suffisants et demande à l'utilisateur de s'authentifier
  5. l'utilisateur le passe, la session a des droits accrus
  6. utilisateur dans l'application, attaquant avec une session privilégiée, profit

Il serait correct de corriger cela sur l'API, en émettant un autre sessionId après une élévation de privilèges, mais nous écrivons une application mobile. Et notre façon est de refuser de transférer le jeton du maître à l'esclave. De plus, cela nous donnera une protection approfondie et si quelque chose casse sur l'API et que les jetons ne changent pas lorsque les privilèges sont augmentés, alors une attaque sera toujours impossible.

Fuite par un tiers


Un autre inconvénient de cette option. De nombreuses personnes utilisent des services tiers pour DeepLink en raison de la commodité de générer des liens, des analyses et d'autres trucs sympas. Dans ce cas, vous remettez simplement votre jeton à une société tierce.

Option # 2: FOURNISSEUR DE CONTENU

Comment allons-nous procéder? Nous définissons le fournisseur de contenu maître et faisons en sorte que l'esclave se rende auprès de ce fournisseur de contenu pour le jeton.



Ainsi, nous nous débarrassons du risque de transférer le jeton vers la mauvaise application en cas de détournement de DeepLink et rendons l'attaque de fixation de session impossible. Mais nous avons d'autres problèmes - dans la version actuelle, en général, toute application peut demander un jeton à tout moment, même si nous n'avons pas initié son lancement.

Niveau de protection


Dans la plupart des cas, vous devez vérifier que l'esclave est signé avec la même clé que le maître, c'est-à-dire qu'il appartient au même auteur. Dans ce cas, le gestionnaire de packages dispose d'une méthode checkSignatures qui vérifie les signatures d'application. Pour utiliser cette fonction, vous devez ajouter une autorisation avec protectionLevel = "signature" dans Content-Provider dans le manifeste d'application:

 <permission android:name="com.example.contentprovider.access" android:protectionLevel="signature"/> <application> <provider ... android:readPermission="com.example.contentprovider.access"> </application> 

Le schéma ne changera guère par rapport à la figure précédente, seule une garantie apparaîtra que seules les applications avec une signature du même auteur auront accès au jeton.

Condition de course de permission


Il y a une caractéristique très désagréable que les noms d'autorisation ne sont pas uniques, qui peuvent être utilisés par une application malveillante et enregistrer l'autorisation avec notre nom et protectionLevel = «normal» devant nous. Dans ce cas, lors de l'installation de notre application, l'autorisation existera déjà sur le système d'exploitation et ne sera pas écrasée. Par conséquent, notre fournisseur de contenu restera non protégé et avec un accès autorisé à partir de n'importe quelle application.

Différentes signatures


Malheureusement, les applications sont loin d'être toujours signées avec une seule clé, par exemple, certaines des applications sont achetées, ou «si historiquement», mais une transition transparente est toujours nécessaire. Dans ce cas, nous prenons la vérification de signature sur nous-mêmes.
Comment cela peut-il être mis en œuvre:
Le Content-Provider a une méthode getCallingPackage (), par laquelle nous pouvons obtenir le packageId de l'application qui a demandé des données, et par packageId nous pouvons obtenir la liste des signatures et les vérifier avec celles intégrées.

 String pkg = this.getCallingPackage(); PackageInfo pkgInfo = pkgmgr.getPackageInfo(pkg, GET_SIGNATURES); Signatures[] signatures = pkgInfo.signatures; for (Signature sig: signatures) { if (sig.equals(TRUSTED_SIGNATURE)) { // trusted signature found, trust the application } } 



Il semble que nous ayons tout fait parfaitement, mais non.

Fausse vulnérabilité d'identification


Le problème est que lorsque Android crée une chaîne de confiance, le processus de vérification compare uniquement le sujet et ne vérifie pas la signature dans le champ du signataire du certificat. Par conséquent, un attaquant peut créer une chaîne de confiance sans signature réelle.

En raison de cette erreur, une chaîne de certificats incorrecte est générée, qui peut inclure des certificats légitimes intégrés dans l'APK, mais pas réellement utilisés pour signer l'application. Au final, je vais laisser un lien vers le commit qui corrige cette vulnérabilité. Le problème est résolu dans Android 4.4, nous ne pouvons donc augmenter le niveau d'API qu'à 19.

Conclusions

Aujourd'hui, nous avons examiné comment les fonctionnalités doivent être analysées pendant le développement.
Nous avons également examiné les options de transfert du secret entre deux applications, au cours desquelles nous avons analysé les problèmes de chaque option et trouvé des moyens de les éviter.

Toutes les applications sécurisées!

Les références

Source: https://habr.com/ru/post/fr448198/


All Articles