Recommandations pour les applications Android

16 mars 2018

Les recommandations abordées dans cet article améliorent la compatibilité entre XenMobile et les applications mobiles pour les appareils Android.

SDK Worx App et encapsulation

Si votre application utilise le SDK Worx App, vous devez utiliser la version de l’outil MDX Toolkit correspondante pour l’encapsulation. Une différence de version entre ces deux composants peut entraîner un fonctionnement incorrect.

Pour éviter ce type d’incohérence, encapsulez l’application avec le type d’application Premium ou General. Cette configuration vous permet de mettre à disposition une application préencapsulée. Par conséquent, le client n’a pas besoin d’encapsuler l’application, ce qui évite l’utilisation d’un MDX Toolkit de version différente. Pour de plus amples informations sur l’encapsulation d’applications, consultez la section Encapsulation des applications mobiles Android dans la documentation du MDX Toolkit.

Ne pas bloquer le thread principal

Vous ne devriez pas utiliser de code de blocage lors de l’exécution sur le thread principal. Il s’agit d’une recommandation Google, mais elle est encore plus importante avec XenMobile. Certaines actions peuvent prendre plus de temps dans une application gérée ou même bloquer l’exécution d’autres threads.

Le code de blocage inclut notamment :

  • Opérations de fichier ou de base de données
  • Opérations de réseau

Pour plus de clarté, toutes les méthodes de cycle de vie des applications, comme onCreate, s’exécutent sur le thread principal.

Google fournit une API StrictMode qui peut vous aider à détecter le code de blocage. Pour plus d’informations, consultez ce billet de blog : http://android-developers.blogspot.com/2010/12/new-gingerbread-api-strictmode.html.

Écrire un code robuste

En particulier, vous devez vérifier les valeurs de retour ou intercepter les exceptions provenant des API d’infrastructure. Bien que ce soit une recommandation courante en programmation, elle est particulièrement importante pour les applications gérées.

Plusieurs API qui fonctionnent sans problème habituellement échouent si des stratégies XenMobile bloquent la fonctionnalité sous-jacente. Les fonctionnalités décrites précédemment en sont des exemples :

  • Les API de réseau échouent comme s’il n’existait aucun réseau disponible.
  • Les API de détection, telles que le GPS et l’appareil photo, renvoient une valeur null ou une exception.
  • Les intents redirigés vers une application non gérée échouent.
  • L’accès aux fichiers et aux bases de données peut échouer s’il est utilisé dans le thread principal. Pour de plus amples informations, consultez les sections Assurer la compatibilité du cryptage de données et Entropie utilisateur dans cet article.

Lorsque vous rencontrez un échec, votre application doit gérer le problème de façon appropriée plutôt que de se bloquer.

Hooking - Limites

MDX injecte les fonctionnalités dans une application Android binaire en modifiant le code DEX dans le APK. Il existe plusieurs limites :

  • XenMobile peut ne pas gérer les classes d’infrastructure des versions de SDK Android antérieures à 4.0. Veillez à éviter ces classes obsolètes.
  • La plupart des fonctionnalités sont injectées dans les API d’infrastructure Java/Android. Le code (C/C ++) natif n’est généralement pas géré. Cependant, même pour le code natif, le cryptage de fichier est toujours appliqué.
  • Le code natif qui utilise JNI pour accéder à la fonctionnalité Java doit uniquement cibler le code dans l’application utilisateur. En d’autres termes, n’utilisez pas JNI pour invoquer directement les méthodes d’infrastructure Java ou Android. Utilisez plutôt le modèle de conception de proxy pour encapsuler la classe d’infrastructure souhaitée dans une classe Java de votre choix. Appelez ensuite votre classe depuis le code natif.

Assurer la compatibilité du cryptage de données

L’une des fonctionnalités principales de MDX est que toutes les données conservées sont cryptées de façon transparente. Vous n’avez pas besoin de modifier votre application pour bénéficier de cette fonctionnalité, et en fait, vous ne pouvez pas directement l’éviter. L’administrateur a la possibilité de désactiver le cryptage de manière sélective ou complètement, mais pas l’application.

Ceci est l’un des aspects plus complexes de MDX et il est important de comprendre les points suivants :

  • Le cryptage de fichier est présent pour l’ensemble du code natif et Java qui s’exécute dans les processus gérés.

  • Certaines API d’infrastructure, telles que les lecteurs média et la prise en charge de l’impression, s’exécutent dans des processus de système d’exploitation séparés. Si vous utilisez une telle API, il est possible que vous rencontriez des problèmes.

    • Exemple : votre application enregistre un fichier sur le disque (crypté) et transmet une référence au fichier à une API multimédia. L’API multimédia tente de lire le fichier mais ne comprend pas le contenu crypté. Elle échoue ou bloque l’application.
    • Exemple : vous créez un descripteur de fichier (qui démarre un fichier crypté) et vous l’attribuez à l’API de caméra. Le processus de caméra écrit directement les données non cryptées dans le fichier crypté. Lorsque votre application tente de lire ces données, les données sont décryptées, générant un texte illisible.
  • Une solution pour gérer les processus séparés consiste à décrypter un fichier avant de le transmettre à l’API appropriée. Ou, si l’API écrit des données, vous laissez l’API écrire les données, puis vous les cryptez une fois que l’API a terminé. Quelques étapes sont nécessaires :

    1. Désignez une zone qui restera non cryptée. Vous devez documenter cette action pour votre client, car un administrateur XenMobile doit créer une stratégie d’exclusion de cryptage.
    2. Pour décrypter, il vous suffit de copier le fichier depuis l’emplacement normal (crypté) vers l’emplacement décrypté. Notez que vous devez effectuer une copie d’octets et non une opération de déplacement de fichier
    3. Pour crypter, effectuez la même opération dans le sens inverse. Copiez depuis des emplacements non cryptés vers des emplacements cryptés.
    4. Supprimez le fichier non crypté lorsqu’il n’est plus requis.
  • Le mappage de mémoire n’est pas pris en charge pour les fichiers cryptés. Si vous appelez une API qui effectue le mappage de mémoire, elle échouera. Vous devez gérer l’erreur. Si possible, évitez d’utiliser de manière directe ou indirecte le mappage de mémoire. Un cas d’utilisation indirecte est la bibliothèque SqlCipher tierce.

    Si vous ne pouvez pas éviter le mappage de mémoire, l’administrateur doit définir une stratégie d’exclusion de cryptage qui ignore les fichiers concernés. Vous devez documenter cette stratégie pour votre client.

  • Le cryptage ajoute une charge significative. Veillez à optimiser le traitement I/O des fichiers pour empêcher la dégradation des performances. Par exemple, si vous lisez et écrivez de manière répétée les mêmes informations, il se peut que vous souhaitiez mettre en place un cache au niveau de l’application.

  • Les bases de données sont simplement des fichiers et elles sont également cryptées. Vous pouvez rencontrer un problème de performance ici aussi. La taille du cache de base de données standard est 2 000 pages ou 8 Mo. Si votre base de données est volumineuse, vous pouvez augmenter cette taille.

    Le mode SQLite WAL n’est pas pris en charge à cause des limites de mappage de mémoire.

Entropie utilisateur

Une option de cryptage XenMobile nécessite que l’utilisateur entre un code PIN avant que la clé de cryptage puisse être générée. Cette option est appelée entropie utilisateur. Elle peut entraîner un problème particulier pour les applications.

Plus spécifiquement, aucun accès fichier ou base de données ne peut être effectué jusqu’à ce que l’utilisateur entre un code PIN. Si une telle opération E/S est présente à un emplacement qui s’exécute avant que l’interface utilisateur du code PIN puisse être affichée, elle échouera toujours. Ce comportement a plusieurs incidences :

  • Gardez les opérations de fichier et de base de données hors du thread principal. Par exemple, une tentative de lecture d’un fichier à partir de la méthode onCreate() de l’objet application échouera toujours.
  • Les opérations en arrière-plan, telles que les fournisseurs de services ou de contenu, peuvent être exécutées même sans activité de l’application. Ces composants d’arrière-plan ne peuvent pas afficher l’interface utilisateur de code PIN et, par conséquent, ils ne peuvent pas effectuer d’accès fichier ou base de données. Veuillez noter que lorsqu’une activité s’exécute dans l’application, les opérations en arrière-plan sont autorisées à réaliser des opérations E/S.

Il existe plusieurs mécanismes d’échec si la clé de cryptage n’est pas disponible en raison de l’entropie utilisateur :

  • Si le thread principal accède à une base de données avant que le code PIN soit disponible, l’application est arrêtée.
  • Si un thread autre que le thread principal accède à une base de données avant que le code PIN soit disponible, ce thread est bloqué jusqu’à ce que le code PIN soit entré.
  • Si un accès à un élément autre qu’une base de données est tenté avant que le code PIN soit disponible, l’opération échoue. Au niveau C, une erreur EACCES est renvoyée. Dans Java, une exception est envoyée.

Pour vous assurer que ce problème ne concerne pas votre application, testez-la avec l’entropie utilisateur activée. La propriété du client XenMobile, Encrypt secrets using Passcode, ajoute l’entropie utilisateur. Vous pouvez configurer cette propriété de client, qui est désactivée par défaut, dans la console XenMobile, sous Configurer > Paramètres > Plus > Propriétés du client.

Réseau et micro VPN

Les administrateurs disposent de plusieurs options de stratégie XenMobile pour le réseau. La stratégie Accès réseau empêche, permet ou redirige l’activité réseau de l’application comme suit :

  • Par défaut, le réseau est complètement bloqué pour une application. Si la stratégie Accès réseau est définie sur Bloqué, les API de réseau utilisées par votre application échouent. Conformément à la recommandation précédente, vous devriez traiter un tel échec de façon appropriée.
  • Si la stratégie Accès réseau est définie sur Non restreint, tous les appels réseau ont un accès direct et ne sont pas tunnélisés.
  • Si la stratégie Accès réseau est définie sur Tunnélisé vers le réseau interne, tous les appels réseau sont tunnélisés via NetScaler Gateway. Dans cette stratégie, le tunneling est contrôlé par la stratégie Mode VPN préféré.

La stratégie Mode VPN préféré définit le mode initial des connexions qui sont tunnelisées sur le réseau interne.

  • Si la stratégie Mode VPN préféré est définie sur Navigation sécurisée, l’URL http/https est réécrite. Le mode Navigation sécurisée peut uniquement tunnéliser le trafic http et https. Un avantage important de Navigation sécurisée est l’authentification unique (SSO) pour le trafic http et https ainsi que l’authentification PKINIT. Sur Android, Navigation sécurisée a une charge de configuration faible et il s’agit donc de l’option préférée pour les opérations de type navigation Web.
  • Si la stratégie Mode VPN préféré est définie sur Tunnel VPN complet, tout le trafic provenant de l’application gérée est tunnélisé via NetScaler Gateway. Sur Android, ce mode exécute un VPN sur tout l’appareil mais son utilisation est limitée aux applications gérées.

Limitation : XenMobile ne prend pas en charge les serveurs socket. Si un serveur socket est exécuté dans l’application encapsulée, le trafic réseau vers le serveur socket n’est pas tunnélisé via NetScaler Gateway.

Prise en charge des infrastructures de développement d’application mobile

Certaines infrastructures d’applications ont des problèmes de compatibilité avec XenMobile :

  • Avec PhoneGap, le service de géolocalisation n’est pas bloqué.
  • SQLCipher ne fonctionne pas avec le cryptage car il utilise le mappage de mémoire. Une solution consiste à ne pas utiliser SQLCipher. Une autre solution consiste à exclure le fichier de base de données du cryptage à l’aide d’une stratégie d’exclusion de cryptage. Un administrateur XenMobile doit configurer la stratégie dans la console XenMobile.

Conseils de débogage

Lors du débogage d’une application encapsulée, suivez ces conseils.

  • Déterminez si le problème est présent dans une version non encapsulée de l’application. Si le problème se produit avec l’application non encapsulée, utilisez les techniques de débogage normales.
  • Essayez de désactiver plusieurs stratégies XenMobile.
    • Cela permet de localiser toute incompatibilité. La désactivation d’une stratégie signifie que MDX n’applique plus la restriction associée, ce qui vous permet de tester ces fonctionnalités comme si l’application n’était pas encapsulée.
    • Si la désactivation d’une stratégie résout le problème, il se peut que l’application ne vérifie pas la présence d’erreurs dans les API associées.
  • Si une application non modifiée mais avec signature renouvelée ne s’exécute pas :
    1. Extrayez le contenu du APK à l’aide de JAR :

      jar xvf {some.apk}

    2. Supprimez le dossier META-INF :

      rm -rf META-INF

    3. Compressez de nouveau le contenu dans un nouveau APK à l’aide de JAR :

      jar cvf {/tmp/new.apk} *

    4. Signez le nouveau APK à l’aide de JARSIGNER :

      jarsigner -keystore {some.keystore} -storepass {keystorepassword} -keypass {keypassword} {/tmp/new.apk} {keyalias}

    5. Si l’application ne s’exécute toujours pas, vous ne pouvez pas encapsuler l’application à l’aide d’un certificat de signature différent de l’APK utilisé à l’origine.

  • Si un .apk décompilé ou recompilé ne s’exécute pas :
    1. Décompilez et recompilez à l’aide de APKTOOL :

      apktool d {some.apk} -o {some.directory}

      apktool b {some.directory} -o {new.apk}

    2. Signez l’APK à l’aide de JARSIGNER comme décrit ci-dessus.

    3. Si l’application ne s’exécute toujours pas, il s’agit d’un bogue APKTOOL externe.

  • Si l’encapsulation d’application ne fonctionne pas :
    1. Essayez de supprimer l’infrastructure APKTOOL et de réencapsuler.
      • Mac/Linux : rm -rf ~/Library/apktool/framework
      • Windows: del /q /s C:\Users{username}\apktool\framework
    2. Comparez l’outil APKTOOL utilisé par le wrapper avec celui que vous avez utilisé pour décompiler et recompiler avec succès à l’étape précédente.
      • S’il s’agit de la même version d’APKTOOL, il existe un bogue dans le wrapper.
      • S’il s’agit d’une autre version d’APKTOOL, il peut s’agir d’un bogue dans le APKTOOL intégré dans le MDX Toolkit.
        1. Extrayez le contenu de ManagedAppUtility.jar.
        2. Remplacez par le contenu de l’APKTOOL.jar que vous avez utilisé pour encapsuler l’application avec succès dans l’étape précédente.
        3. Compressez de nouveau le contenu dans un nouveau ManagedAppUtility.jar.
        4. Encapsulez l’application pour confirmer le bogue dans l’APKTOOL intégré.
  • Exécutez l’application encapsulée et capturez les informations du journal.
    1. Utilisez grep pour déterminer ce qui se produit dans l’application.

      Pour suivre les activités de l’application : grep “MDX-Activity”

      Pour suivre le verrouillage MDX de l’application : grep “MDX-Locked”

      Pour voir les deux journaux ensemble : egrep “MDX-Act|MDX-Loc”

    2. Si une erreur indiquant que l’application ne répond pas s’affiche, vous pouvez extraire les traces ANR à l’aide d’ADB.

  • Si un problème se produit lors de l’interaction avec de multiples applications, par exemple lors de l’utilisation de la fonction Ouvrir dans :
    1. Vérifiez que les stratégies de cryptage et les paramètres de groupe de sécurité sont les mêmes pour toutes les applications.
    2. Essayez une autre application. Il peut exister un bogue dans l’une des applications testées.
    3. Capturez les journaux de toutes les applications concernées. Notez que Secure Hub peut regrouper les journaux et envoyer les journaux par e-mail depuis les applications individuelles. À partir de l’écran de My Apps (Mes applications), balayez vers la droite pour accéder à l’écran d’assistance. Ensuite, cliquez sur le bouton Need Help (Besoin d’aide) dans le bas de l’écran.

Outre les outils mentionnés ci-dessus, les opérations suivantes peuvent également vous aider :

  • Utilisez AAPT pour vider les informations sur l’application.

    aapt dump badging {some.apk}

  • Utilisez la commande DUMPSYS sur l’appareil.

    adb shell dumpsys 2>&1 | tee {dumpsys.out}

  • Utilisez DEX2JAR pour recompiler les classes en pseudo-Java.

    dex2jar {some.apk}

    Convertissez les classes depuis les applications encapsulées Dual-Dex :

    apktool d {some.apk} -o {some.dir}

    dex2jar {some.dir}/assets/secondary-1.dex

  • Utilisez JD-GUI pour afficher le code pseudo-Java.

  • Utilisez BAKSMALI pour décompiler les classes d’application depuis les applications encapsulées Dual-Dex.

    • Décompilez l’APK encapsulé :

      apktool d {some.apk} -o {some.dir}

    • Décompilez les classes de l’application qui ne sont pas décompilées par l’appel ci-dessus :

      baksmali {some.dir}/assets/secondary-1.dex -o {some.dir}/smali