Bloquer le texte en clair dans les applis Android sans dépendre d'un VPN
Le texte en clair dans la charge et le texte en clair sur le chemin sont deux problèmes distincts. Corrigez le premier dans l'appli, le second avec un tunnel ou une politique d'appareil.
Deux choses très différentes portent le nom de blocage du texte en clair sous Android. L'une est une politique interne à une application, qui demande à sa propre pile réseau de refuser le HTTP simple. L'autre est un dispositif au niveau de l'appareil qui tente de tout protéger sur le téléphone d'un coup, généralement en faisant passer le trafic par un VPN. Elles résolvent des problèmes différents, et la seconde ne peut pas corriger la première : un tunnel protège le segment entre le téléphone et la sortie, alors qu'une application qui parle HTTP continue de parler HTTP à tout ce qui se trouve au-delà de cette sortie.
Deux problèmes sous un même nom
Le premier problème est la charge : l'application écrit des identifiants ou des jetons dans une requête qui n'est pas chiffrée de bout en bout, si bien que chaque saut qui peut la voir peut la lire. Le second est le chemin : l'application peut être parfaitement correcte, et vous voulez malgré tout que l'opérateur Wi-Fi local n'apprenne rien de l'endroit où elle se connecte. Un VPN traite le second et seulement le second.
Cette distinction détermine à qui appartient la correction. La charge appartient à celui qui livre l'application, car seul ce code décide quelle URL est appelée et si un certificat est validé. Le chemin appartient à l'appareil ou au réseau, car il s'agit de savoir où voyagent les paquets, et non ce qu'ils contiennent.
Chemin un : l'application que vous contrôlez
Si vous livrez l'application, la correction est une décision de transport doublée d'une politique qui l'impose. Pointez chaque point de terminaison vers HTTPS, laissez la validation du nom d'hôte et du certificat activée, et supprimez le repli en HTTP simple au lieu de le laisser à un indicateur de configuration de distance. Une redirection n'aide pas ici : une requête HTTP qui reçoit un 301 a déjà envoyé ses en-têtes et son corps en clair, donc des identifiants ne doivent jamais circuler en supposant que la redirection les protégera.
À partir d'Android 7.0, Network Security Configuration exprime la politique. Le fichier ci-dessous en est la plus petite version utile : il refuse le texte en clair partout, sauf si une exception propre à un domaine dit le contraire.
<network-security-config>
<base-config cleartextTrafficPermitted="false" />
</network-security-config>Référencez cette ressource depuis le manifeste, puis lisez les exceptions déjà présentes avant de livrer. Un ancien domaine de débogage ou une entrée SDK d'un fournisseur de paiement peut discrètement rétablir le texte en clair pour l'hôte que vous cherchiez à protéger.
Deux détails de version méritent d'être connus. Les applications ciblant l'API 28 ou plus refusent déjà le texte en clair par défaut, donc une application qui parle encore HTTP simple cible soit un niveau d'API plus ancien, soit a une exception quelque part. Et lorsqu'une configuration de sécurité réseau est présente, l'ancien attribut de manifeste android:usesCleartextTraffic ne tranche plus la question, ce qui explique pourquoi modifier cet indicateur semble parfois sans effet.
Chemin deux : l'application que vous ne contrôlez pas
Pour une application tierce installée, vous ne pouvez pas réécrire sa configuration de sécurité par un réglage utilisateur. Les options réalistes sont les contrôles de connexion sécurisée du produit lui-même, une alternative maintenue qui utilise déjà TLS, ou une politique d'appareil géré qui limite ce que l'appareil peut exécuter. Ce sont des engagements différents, et seul le troisième passe à l'échelle d'un parc.
Les règles réseau sont des substituts plus faibles qu'elles n'en ont l'air. N'autoriser que le port 443 n'impose pas TLS authentifié, car beaucoup de protocoles en texte clair peuvent être déplacés sur ce port, et bloquer le port 80 ne couvre pas le texte en clair sur d'autres ports. Le mode HTTPS uniquement d'un navigateur est lui aussi limité à ce navigateur, et non à une application de courrier ou de messagerie distincte sur le même téléphone.
Installer un certificat d'interception pour que le trafic paraisse chiffré est un changement de confiance, pas une correction. Cela remplace l'authentification du serveur de l'application par la vôtre, et une application qui ne validait pas les certificats au départ n'est pas réparée par cela ; vous avez seulement déplacé qui peut lire le flux.
Où un VPN aide et où il n'aide pas
Un tunnel est le bon outil lorsque l'exigence est que le réseau local n'apprenne rien de la connexion, ou que l'application atteigne un service privé qu'elle ne peut pas atteindre autrement. C'est le mauvais outil pour faire parler HTTPS à un client HTTP, car la requête quitte le tunnel exactement telle qu'elle y est entrée.
Android ajoute une contrainte pratique : la plateforme n'exécute qu'un seul service VPN à la fois. Une application de filtrage locale qui prend cette place entre en concurrence avec le tunnel distant dont vous avez réellement besoin, et basculer entre les deux est une opération au niveau de l'appareil, pas de l'application. Cette place unique est une bonne raison de mettre la politique de charge dans l'application et de réserver le tunnel au chemin.
Le seul cas où les deux se recoupent est un serveur privé que vous exploitez aussi. Là, un tunnel peut rendre le chemin privé même si le protocole reste du texte en clair, ce qui réduit l'exposition mais ne change pas ce qu'est la charge. Traitez cela comme une réduction du risque, non comme un chiffrement des données.
Ce qu'il faut tester avant de le déclarer bloqué
Commencez par le défaut qui surprend : une application ciblant l'API 28 ou plus devrait déjà refuser le texte en clair, donc vérifiez le niveau cible avant d'ajouter une configuration qui duplique un défaut. Puis testez délibérément le cas d'échec : une requête vers un hôte HTTP simple doit échouer et non réussir silencieusement via un repli.
adb shell dumpsys package com.example.app | grep -E 'targetSdk|versionName'
adb logcat | grep -i cleartextPour le cas de réussite, confirmez que l'appel HTTPS valide une véritable chaîne de certificats et qu'un proxy doté d'un certificat non fiable est rejeté plutôt que toléré. Une poignée de main qui réussit contre n'importe quel certificat n'a rien prouvé sur la sécurité du transport.
Pour une application tierce, notez la limite que vous pouvez réellement imposer, qu'il s'agisse d'une politique d'appareil géré, d'une règle réseau ou de rien, et dites-le dans les critères d'acceptation. Le guide de configuration de la sécurité Android liste les valeurs par défaut de la plateforme et les composants qui respectent la politique, et c'est la partie qui décide si votre configuration fait quoi que ce soit.