GrapheneOS et Play services : comment ça marche ?

GrapheneOS a récemment développé une méthode de compatibilité avec les Google Play services, permettant d'accroître sa compatibilité avec les applications Android. Regardons en détails le fonctionnement de cette méthode alternative.

GrapheneOS et Play services : comment ça marche ?

Intro

Il y a quelques temps, j'effleurais une seconde fois les différents champs de travail de GrapheneOS, l'OS sûr et respectueux de la vie privée compatible avec l'écosystème d'applications Android.

GrapheneOS : présentation en détails de l’OS et du projet
GrapheneOS est un système d’exploitation mobile basé sur le code source d’Android (AOSP), compatible avec son écosystème d’applications, et visant à renforcer la sécurité et la vie privée. Revenons ensemble sur l’état de cet OS open-source alternatif en 2021 !

Dans la sphère des blogs technologiques francophones, nous sommes peu nombreux à parler de GrapheneOS. Il est donc non seulement difficile d'obtenir des informations claires et précises sur cet OS, mais également de suivre son évolution. Pour être clair, je ne suis pas un développeur principal de l'équipe : je suis un membre investi de la communauté, donateur, et contributeur occasionnel (et j'ai en projet d'accélérer ces contributions).

Contrairement à ce que j'ai parfois pu lire, GrapheneOS se veut être accessible pour le plus grand nombre. Ce n'est pas un OS réservé aux techies, mais un OS qui a vocation à pouvoir être utilisé par à peu près tout le monde. C'est dans cette idée qu'un champ de travail a été mené pour améliorer considérablement l'accessibilité. Entre autres, nous pouvons citer :

  • L'arrivée de l'installateur Web qui simplifie énormément l'installation de l'OS. Tout se passe directement depuis votre navigateur, que ce soit sur Windows, macOS, Linux, ou encore un smartphone Android !
  • D'autres fonctionnalités sont en développement, tel qu'un marché d'applications simple et sûr, qui proposera des builds de Signal ou Element par exemple. Nous en reparlerons le jour où ce sera assez avancé.
  • Et depuis quelques semaines… le support des Play services ! Cela devrait massivement renforcer la compatibilité des applications Android avec GrapheneOS.

Cet article sera donc consacré à expliquer comment ce support a été rendu possible, en quoi il consiste, ses limitations et enfin pourquoi cette approche a été retenue par GrapheneOS plutôt qu'une autre (à savoir microG).

Rappel sur les Play services

  • Il s'agit d'un ensemble de fonctionnalités propriétaires développées par Google pour son OS Android, dont le développement ne fait pas partie d'AOSP (Android Open Source Project).
  • Le code des Play services est inclus dans les distributions commerciales d'Android (donc l'immense majorité). C'est un code normalement privilégié au sein du système, et donc une surface d'attaque supplémentaire.
  • De nombreuses applications utilisent le SDK des Play Services et en sont donc dépendantes pour au moins une partie de leurs fonctionnalités.
  • Parmi ces fonctionnalités, on retrouve les notifications push qui reposent souvent sur Firebase Cloud Messaging (FCM).

On retrouve d'autres fonctionnalités également qui peuvent être considérées comme invasives pour la vie privée. Notez cependant qu'une application peut tout de même utiliser des services Google sans Play services pour autant : comme le SDK Google Mobile Ads qui n'en a pas besoin puisque le code est inclus dans l'application, à l'exception de la version Lite dudit SDK qui dépend du code fourni par les Play services.

Sandboxed Play services

"Sandboxed", comment ça ?

Pour être plus exact, GrapheneOS supporte les Play services dans leur propre sandbox. Cela n'a rien de très spécial dit ainsi, puisque nous savons déjà que toutes les applications sur Android ont leur propre sandbox. En d'autres termes, GrapheneOS supporte l'installation des Play services comme une application tout à fait normale.

C'est une solution élégante mais également pratique :

  • Il n'y a pas besoin de télécharger une version séparée de GrapheneOS.
  • Les Play services peuvent être installés et désinstallés à votre guise.
  • Les profils utilisateur d'Android peuvent être mis à profit !

En effet, imaginez que vous souhaitez faire fonctionner votre application bancaire désespérément, qui a une dépendance forte sur les Play services. Cependant, vous ne voulez pas installer les Play services sur votre profil principal : dans ce cas, vous pouvez installer tout ceci sur un profil secondaire complètement isolé du profil principal.

Concrètement, Google verra autant de "smartphones" qu'il n'y a de profils avec les Play services actifs.

Mais comme je l'écrivais ci-dessus, les Play services sont sandboxed contrairement à leur distribution classique privilégiée au sein du système. Par défaut, ils n'auront donc accès à aucune permission particulièrement invasive. Les applications installées sur le même profil peuvent quand même détecter la présence des Play services et communiquer avec (IPC), donc l'utilisation d'un profil secondaire peut faire sens si vous ne souhaitez pas qu'une application se mette à utiliser les Play services alors qu'elle fonctionnait bien en leur absence.

Le domaine untrusted_app

Sur Android, toutes les applications sont sandboxed et sont donc considérées comme untrusted_app par le système : suivant les principes de la Zero Trust Security, aucune confiance spéciale n'est donc accordée aux applications que vous installez et son domaine d'action sera régi par les mêmes règles que les autres.

Le modèle de sécurité mobile : Android, iOS, “Linux phones”
Petite incursion dans le monde de la sécurité mobile. Qu’en est-il de son modèle de sécurité ? Quels sont les moyens mis en oeuvre par ses acteurs principaux ?
Nous avions effleuré ce concept dans cet article !
Certaines applications systèmes adoptent une sandbox moins restreinte priv_app avec des exceptions supplémentaires, mais GrapheneOS mène un travail de restriction y compris sur ces applications.

En l'occurrence et non-exhaustivement, la sandbox des applications sur Android est définie par des règles SELinux strictes qui évoluent au fur et à mesure des versions d'Android. C'est la raison pour laquelle il faut d'ailleurs privilégier des applications modernes qui exploitent un niveau d'SDK récent (30 pour Android 11 par exemple), car elles peuvent entre autres bénéficier d'une sandbox plus robuste que des applications qui ciblent un niveau d'SDK plus ancien.

On peut par exemple constater sur Android 11 que pour le niveau d'SDK 25 de nombreuses exceptions à la sandbox sont faites pour maintenir la compatibilité :

# b/35917228 - /proc/misc access
# This will go away in a future Android release
allow untrusted_app_25 proc_misc:file r_file_perms;

# Access to /proc/tty/drivers, to allow apps to determine if they
# are running in an emulated environment.
# b/33214085 b/33814662 b/33791054 b/33211769
# https://github.com/strazzere/anti-emulator/blob/master/AntiEmulator/src/diff/strazzere/anti/emulator/FindEmulator.java
# This will go away in a future Android release
allow untrusted_app_25 proc_tty_drivers:file r_file_perms;
Un simple échantillon de ces exceptions
Google Camera est une exception à untrusted_app sur les Pixel car il dispose d'un domaine d'accès supplémentaire (pour DSP). Aussi, certaines apps peuvent en guise de bonne pratique utiliser une sandbox interne encore plus renforcée : isolated_app via isolatedProcess.

Historiquement, Play services a longtemps été contenu dans le domaine priv_app normalement réservé à des applications système privilégiées, mais il dispose désormais de son propre domaine depuis que Google a décidé de restreindre davantage priv_app dans Android. Ce domaine pourrait être gmscore_app d'après mes recherches dans le code source d'AOSP : vous pouvez constater par vous-même les privilèges octroyés.

Play services est donc sur les distributions traditionnelles d'Android un code propriétaire privilégié, ce qui constitue une surface d'attaque supplémentaire en plus de poser des questions de vie privée.

Le développement de shims

Bien sûr, il est inconcevable d'espérer pouvoir installer les Play services sur Android pur simplement en espérant que "ça fonctionne", puisqu'ils n'ont jamais été conçus pour fonctionner comme une application normale et non-privilégiée.

L'approche de GrapheneOS est donc de forcer Play services de fonctionner dans le domaine untrusted_app comme une application normale. C'est un choix sans compromis sur la sécurité, mais il a fallu cependant développer des shims dans GrapheneOS car les Play services ne sont pas conçus pour fonctionner dans ce domaine.

Ces shims sont des morceaux de code qui "apprennent" en quelque sorte aux Play services à fonctionner avec des permissions très restreintes. Les shims sont conçus pour le plus souvent retourner des données génériques, afin que les Play services ne plantent pas bêtement. Ils permettent également aux notifications de fonctionner, ce qui est la bienvenue pour profiter des notifications push via FCM (Firebase Cloud Messaging).

Le support des dynamites modules est également arrivé, bien que plus tardivement : ce sont des modules téléchargés depuis Google Play et qui peuvent être utilisés par un ensemble d'apps qui utilisent le SDK des Play services. L'implémentation de GrapheneOS utilise memfd pour partager les modules entre différentes applications plutôt que l'implémentation par défaut qui demande des privilèges et de nouvelles exceptions SELinux.

Ce développement a été rendu possible grâce aux multiples contributions de kdragon. Donc nous lui devons un grand merci !

Les limitations

"Tout ceci est trop beau pour être vrai", pourriez-vous penser. Mais ce n'est pas un rêve : GrapheneOS propose une compatibilité sans compromis sur la sécurité et la vie privée. Bien évidemment, ce que vous en faites après vous regarde : cela ne rend pas l'utilisation de services Google anonyme, mais cela vous donne le choix de les utiliser ou non, et de décider de quelles données ils auront accès.

SafetyNet est la première limitation : c'est une API qui peut être utilisée par l'application pour déterminer entre autres si l'OS utilisé est certifié par Google. Il n'est pas prévu par GrapheneOS de tromper SafetyNet, cependant il est suggéré de contacter les développeurs et de leur indiquer d'utiliser l'API d'attestation hardware d'AOSP et d'y ajouter les empreintes des clés verified boot de GrapheneOS.

GrapheneOS attestation compatibility guide
Guide on using remote attestation in a way that’s compatible with GrapheneOS.

Le Google Play Store est une autre limitation, en quelque sorte : il peut et doit être installé car il fournit des API nécessaires, mais il ne peut pas vraiment être utilisé pour installer des applications directement du fait de son manque de privilèges pour utiliser l'API permettant d'installer les applications "silencieusement" (unattended app install). En attendant qu'un shim permette ceci, il faut toujours utiliser Aurora Store.

En général, les fonctionnalités privilégiées par nature ne pourront pas fonctionner, comme Google Pay.

Par contre, aucune autre limitation ne me vient encore à l'esprit en dehors de quelques shims dont le développement n'est pas terminé. La grande majorité des applications dépendantes des Play services, y compris les propres applications de Google, devraient fonctionner avec l'implémentation actuelle.

Et pourquoi pas microG ?

Cette question revient sans cesse donc il convient de l'aborder. microG est une réimplémentation open-source des différentes APIs des Play services, mais son intégration n'a jamais été retenue pour plusieurs raisons :

  • Par sa nature même d'être une réimplémentation, ses fonctionnalités n'atteindront jamais 100% celles proposées par les Play services. Seules les APIs les plus communes sont implémentées.
  • microG manque des mécanismes de sécurité pourtant utilisés par les Play services, comme l'épinglage de certificats des services Play.
  • microG nécessite que l'OS supporte le signature spoofing, en somme l'usurpation de signature pour qu'il puisse être reconnu "comme" les Play services. Cela compromet le modèle de sécurité d'Android.
  • Enfin, tout comme les Play services, microG nécessite toujours des privilèges particulièrement élevés au sein du système.

Si vous avez suivi mon blog, le mot "open-source" ne fait pas tout et il peut même s'avérer trompeur. Concrètement, microG n'est pas magique :

  • Il effectue plus ou moins les mêmes connexions aux serveurs Google (puisque celles-ci passent de toute façon par ces serveurs, comme FCM).
  • Il n'évite pas des situations où les applications utilisent des APIs Play elles-mêmes, comme nous l'avons plus haut avec le SDK Google Mobile Ads (qui n'est qu'un exemple parmi d'autres).

J'ai donc toujours été perplexe quant aux arguments avancés de la "vie privée supplémentaire" offerte par microG.

Evidence-based security
En écho à la “broscience” (usuellement de la désinformation scientifique par des personnes non-compétentes), je souhaite m’adresser dans cette série d’articles à des mythes persistants de la sécurité informatique, qui n’ont jamais été corrects, ou bien obsolètes.
Cf. la partie sur l'open-source
Que le code soit open-source ou non, il ne doit pas être plus privilégié que nécessaire. Déjà parce qu'il ne fait pas forcément ce que vous attendez de lui, mais aussi car il peut être exploité.

Un autre exemple assez criant est ce bug de microG présent depuis plus de 7 ans et qui faisait fuiter le mot de passe de votre compte Google via logcat (lequel peut être accessible via adb par exemple). C'est une très mauvaise pratique de laisser de telles informations sensibles dans des logs.

L'approche de GrapheneOS n'est pas de perdre son temps à réimplémenter des APIs et à maintenir cette réimplémentation, mais de faire fonctionner les Play services de façon non-privilégiée (au simple prix de perdre certaines fonctionnalités), ce qui est une meilleure approche sur tous les points.

Installation

Si vous utilisez déjà GrapheneOS, il suffit de suivre la section du site officiel :

GrapheneOS usage guide
Usage instructions for GrapheneOS, a security and privacy focused mobile OS with Android app compatibility.

Il faut donc installer 3 composantes (suivre l'ordre) :

Certaines de ces APKs étant splittées, il faut passer par un installateur comme SAI. Vous pouvez d'ailleur utiliser cette application sans lui donner la permission d'accéder au stockage externe, contrairement à ce qu'elle prétend (je n'ai pas de meilleure proposition pour une application du genre).

GitHub - Aefyr/SAI: Android split APKs installer
Android split APKs installer. Contribute to Aefyr/SAI development by creating an account on GitHub.

Dans le futur, ces APKs seront distribuées via le marché d'applications de GrapheneOS, permettant de les installer plus facilement mais aussi de les mettre à jour. Il faut faire les mises à jour manuellement pour l'instant.

N'oubliez pas de suivre attentivement les autres instructions qui consistent par exemple à désactiver les optimisations de batterie pour les Play services, lui permettant essentiellement de fonctionner en arrière-plan.

Personnellement, j'ai opté pour cacher les notifications persistantes des shims. Vous pouvez les cacher dans les paramètres des notifications des Play services ainsi que du Play Store ("Services" en-dessous de "Compatibilty").

Bien que les Play services soient tout à fait utilisables sur le profil principal, la bonne pratique consiste à les isoler sur un profil secondaire avec les applications qui en ont besoin, pour des raisons énoncées ci-dessus.

Il est également possible de révoquer la permission capteurs (sensors), mais certaines fonctionnalités dépendantes des Play services pourraient en avoir besoin (boussole notamment) ; de même pour la permission de localisation, donc cela dépend vraiment de ce dont vous avez besoin.

En effet, certaines applications peuvent utiliser des APIs fournies directement par l'OS en cas d'absence des Play services ; tandis qu'en leur présence, ces mêmes applications privilégient les APIs fournies par les Play services. C'est notamment le cas pour Google Maps et autres applications de localisation. C'est une situation similaire pour les applications qui ont leur propre solution de push comme Signal. Elles utilisent FCM en la présence de Play services, sinon elles utilisent leur solution maison (dans le meilleur des cas) qui fonctionne sensiblement de la même façon que FCM (bien que ce dernier soit en théorie plus optimisé pour un certain nombre de raisons).

Certaines applications ne vérifient la présence des Play services qu'au démarrage initial, donc il faut parfois les réinstaller pour qu'elles puissent "prendre en compte" l'installation a posteriori des Play services.

Outro

Je terminerai cet article en faisant un point clair : GrapheneOS ne sera jamais distribué avec les Play services.

GrapheneOS a simplement développé des méthodes de compatibilité permettant aux Play services de fonctionner tout comme une autre application. L'idée est donc de permettre le choix à l'utilisateur final (qui peut aussi simplement les installer sur un profil utilisateur secondaire) et par une façon qui ne mettrait pas sa sécurité en danger.

Quelques notes de mon utilisation au quotidien :

  • Désormais, il est possible pour moi d'utiliser mon application bancaire depuis mon Pixel 3a sous GrapheneOS alors que je devais auparavant passer par mon iPad pour valider des opérations.
  • Les notifications push ProtonMail ou encore Discord (par exemple) fonctionnent aussi désormais.
  • Il est également possible pour tout le monde d'utiliser la dernière version officielle de Google Camera, qu'on ne présente plus et qui prend des clichés extraordinaires sur des Google Pixel.

Comme je le vois, il y a maintenant très peu de barrières à l'installation et l'utilisation de GrapheneOS. Je suis convaincu que cette fonctionnalité va permettre à de nombreuses personnes d'être plus confiantes dans leur choix de sauter le pas, et ce n'est que le début.

En espérant n'avoir rien oublié, auquel cas je mettrai à jour cet article. En cas de problème avec la fonctionnalité, veuillez le communiquer sur les channels Matrix de GrapheneOS.