Getty Images/Hero Images

Comment Pegasus s’infiltre dans un iPhone

Cet article résume les rapports techniques publiés par Amnesty International, Citizen Lab et Lookout sur les méthodes employées par le logiciel espion pour contaminer un iPhone, en prendre le contrôle et extraire ses données.

C’est l’affaire dans l’affaire. Les enquêtes récentes du consortium de journalistes Forbidden Stories – à lire sur LeMonde.fr, dans les articles de la cellule investigation de Radio France ou sur Mediapart, notamment – ont révélé que le logiciel espion Pegasus de l’éditeur israélien NSO avait été utilisé par des États pour mettre sur écoute des personnalités qui n’ont rien à voir avec le terrorisme. Mais au-delà du scandale géopolitique, il y a un constat technique : il est donc bien toujours possible, malgré les publicités d’Apple qui prétendent le contraire, d’infiltrer un iPhone. Comment est-ce possible ?

Cet article résume les techniques employées par NSO que les experts d’Amnesty International ont mises à jour et expliquées dans un rapport très complet. Ces techniques sont les déclinaisons de méthodes d’infiltration appliquées depuis au moins 2015 par NSO et qui avaient déjà été décrites par le bureau d’études Lockout dans un autre rapport technique paru en 2016 et, lui aussi, très détaillé.

Autre source de cet article, les recherches menées par le laboratoire canadien Citizen Lab, qui étudie les menaces informatiques à l’échelle géopolitique. L’une de ses études, parue en décembre 2020, s’attache notamment à décrire le principe de l’attaque par « Zéro clic », où la victime n’a même plus à appuyer sur un lien frauduleux pour se faire infecter.

Le principe de fonctionnement de Pegasus

Le principe de Pegasus et de tout logiciel espion est une attaque en trois phases : contaminer l’iPhone de la victime, se rendre maître de son système, voler ses contenus. Prenons le problème à rebours. La dernière phase est la plus simple, car, vus de l’intérieur, les smartphones sous iOS ou Android fonctionnent exactement comme des ordinateurs sous Linux. Les apps sauvegardent toutes leurs données dans des fichiers, le plus souvent de petites bases de données au format SQLite, et il existe pléthore d’outils Open source compatibles iOS pour les copier vers le serveur distant de l’espion (rsync, scp, rcp, sftp, ftp...). Sur son site dédié aux développeurs, Apple indique aussi comment programmer des outils pour utiliser la caméra ou le micro de l’appareil.

L’inconvénient est que ces commandes Open source n’existent pas par défaut sur iOS. Comme pour les outils que l’on programmerait soi-même, il faut les installer, mais iOS ne permet pas d’installer autre chose que les Apps issues de l’Apple Store. Contourner cette difficulté est le but de la seconde phase, la plus difficile. La seule chose qui puisse entrer dans un iPhone en dehors du cadre très réglementé de l’Apple Store, ce sont des données (messages, pages web, photos, vidéos...). La technique utilisée par Pegasus et les autres logiciels espions pour transformer des données passives en commandes exécutables serait celle du Bufffer OverRun.

Le Buffer OverRun consiste à charger en mémoire des données à la taille plus importante que prévu, de sorte qu’elles écrasent avec leur contenu les instructions suivantes d’un programme légitime. C’est possible, car les séquences de données entrantes comprennent à la fois les données brutes et des informations qui les décrivent. Parmi les systèmes descriptifs, le plus évolué et le plus intéressant est JavaScript.

JavaScript permet d’exécuter des algorithmes, mais avec des instructions si limitées qu’elles ne sauraient en aucun cas servir à prendre le contrôle d’un appareil. En revanche, ces instructions, écrites en langage courant par les développeurs web, sont traduites à la volée en instructions binaires lorsque l’appareil les exécute. Et, en binaire, les possibilités sont, ce coup-ci, illimitées.

L’infection consiste donc à faire lire à l’appareil un javascript malicieux, qui traite les données qu’il embarque en se trompant sur leur taille. Lorsque l’instruction de traitement est traduite en binaire, elle charge les données en mémoire au-delà de ce qu’elle avait indiqué au système. Les données en trop écrasent les instructions suivantes qui ont déjà été traduites en binaire.

Pour que ce dispositif fonctionne, l’algorithme en JavaScript exécute une suite d’instructions en boucle et il ne charge les données qu’une fois tout le code de la boucle traduit en binaire. Lorsque les données ont été chargées en mémoire, le système n’exécute plus les instructions suivantes, mais les données qui les remplacent. Et, bien entendu, ces données n’étaient ni du texte lisible, ni des pixels colorés, mais bien des codes correspondant aux instructions binaires d’un programme offensif.

Les puristes tiennent manifestement à distinguer le Buffer OverRun du plus connu Buffer Overflow, une technique utilisée depuis la nuit des temps par les logiciels espions. Le Buffer Overflow fait planter un programme avec des données trop importantes. Dès lors, le programme se termine en laissant à la disposition de l’attaquant le Shell depuis lequel il s’était lancé. Et depuis lequel l’attaquant va pouvoir installer et lancer ses propres commandes. Cependant, des systèmes comme iOS et Android sont désormais protégés contre de telles attaques, ne serait-ce que par leur absence de Shell.

Mais pour que tout ceci se déroule, il faut que l’iPhone de l’utilisateur capture au départ les données en question. Celles-ci se trouvant sur les serveurs plus ou moins cachés par Pegasus quelque part sur Internet, il y a peu de chance qu’un utilisateur les visite par hasard avec son téléphone. Faire en sorte que l’iPhone de la victime contracte les bonnes données est le but de la première phase.

Phase 1 : comment le malware est contracté par la victime

Plusieurs méthodes ont existé depuis 2015. La plus simple consistait à envoyer un SMS publicitaire à la victime et à l’inviter à faire cesser le spam en appuyant sur un lien « Stop SMS » indiqué au bas du message. Cliquer sur un lien depuis un SMS sur un iPhone ouvre automatiquement le navigateur Safari avec son moteur d’exécution JavaScript. Évidemment, il s’agissait d’un lien vers les serveurs de Pegasus, lesquels renvoyaient à Safari le javascript malicieux. La même méthode avait été utilisée sur WhatsApp, où l’on est plus incité à cliquer sur un lien envoyé par ce que l’on pense être un contact. L’éditeur a rapidement découvert cette tentative d’intrusion et a protégé son application contre elle.

La méthode la plus élaborée consiste à détourner le trafic normal de l’utilisateur. Elle est élaborée, car l’attaquant doit nécessairement avoir accès à l’infrastructure de réseau mobile auquel est connecté l’utilisateur. C’est-à-dire à la borne Wifi d’un hôtel, à minima, voire à l’opérateur téléphonique de l’abonné. Dans ce dernier cas, l’attaquant est a priori une haute autorité du pays dans lequel agit cet opérateur. C’est l’un des indices qui incite Forbidden Stories à penser que le Maroc serait derrière l’espionnage de son journaliste Omar Radi, car c’est en visitant l’URL légitime leparisien.fr depuis une borne de téléphonie mobile en 2019 que Pegasus aurait infecté son iPhone.

Les méthodes évoluent au gré des habitudes des victimes, mais aussi au fur et à mesure qu’Apple protège son système. Le navigateur Safari, par exemple, est désormais censé empêcher le JavaScript d’un site web de mettre en mémoire des données plus importantes que prévu. C’est en tout cas ainsi que cela se déroule quand Safari est sollicité pour lire une page web.

Pour autant, il existe d’autres méthodes pour lancer l’exécution d’un JavaScript. Les dernières évolutions de Pegasus semblent montrer qu’il suffit d’envoyer à la victime des photos ou des musiques erronées via iMessage ou FaceTime pour les faire planter, les obliger à redémarrer en lançant les services Apple Photos ou Apple Music, lesquels cherchent à leur tour à interpréter le lien en demandant à Safari d’exécuter le JavaScript qui se trouve au bout. Ce que Safari fait, mais sans vérifier que le JavaScript n’écrasera pas ses propres instructions avec du code malicieux, car il a été communiqué par d’autres applications Apple, de confiance.

Dans le courant du mois de juillet 2021, Amnesty International a même détecté une attaque similaire qui, cette fois-ci, faisait cheminer le lien frauduleux d’iMessage à Safari en passant par le processus com.apple.coretelephony, à savoir le moteur qui assure les fonctions basiques de téléphonie dans un iPhone. L’attaque s’est déroulée sur un iPhone 7, fonctionnant sous iOS 14.3, soit l’une des toutes dernières mises à jour du système.

Raffinement ultime : ces infections récentes n’ont même pas à attendre que l’utilisateur appuie sur un lien. Elles se déclenchent toutes seules, dès la réception du message par iMessage ou FaceTime.  

Phase 2 : comment le malware prend possession de l’iPhone

Le Javascript avec des instructions limitées qui écrase ses propres données avec des instructions binaires capables de parler au système – comme le ferait une application issue de l’Apple Store – n’est qu’une amorce destinée à faire tomber les protections du système, pour télécharger, installer et lancer ensuite furtivement tous les outils qui serviront à extraire les données de l’appareil.

Le problème à ce stade est que le programme malicieux a les mêmes limites que n’importe quelle application téléchargée depuis l’Apple Store : il n’accède à aucun Shell pour exécuter des commandes. Et, pire, il ne voit qu’une toute partie des données de l’appareil, en l’occurrence, celles de la session Safari en cours qui l’exécute, car Apple cantonne chaque application dans une sandbox, c’est-à-dire une coquille virtuelle qui empêche toute application d’aller lire des données situées en dehors de son propre répertoire.

Pour contourner ces difficultés, le programme offensif va utiliser les propres fonctions du système hôte, ou plutôt de son noyau, en envoyant des ordres à l’endroit de la mémoire du Smartphone où elles sont censées se trouver. Oui, mais il y a un hic : Apple avait prévu une telle manigance. À chaque redémarrage d’un iPhone, le système charge son noyau à une adresse aléatoire. NSO a manifestement trouvé la parade : il suffit de soumettre au système des informations sans intérêt et de lui demander ensuite où il les a mises pour déduire les adresses auxquelles on peut interroger le noyau.

Une fois qu’il sait où taper, le programme-espion va désactiver dans la mémoire de l’iPhone le dispositif qui interdit d’installer des exécutables autres que ceux signés par Apple (com.apple.driver.AppleMobileFileIntegrity), celui qui interdit de naviguer sur le système de fichiers (com.apple.driver. LightweightVolumeManager) et celui qui vérifie qu’une commande a bien le droit d’accéder à tous les fichiers (setreuid).

Cela fait, il exécute une autre partie de l’algorithme manifestement cachée ailleurs dans les données importées avec le JavaScript. Cette partie intègre le code des commandes Open source mount et chmod, qui servent respectivement à monter le système de fichiers pour naviguer librement dedans et changer les droits d’accès. À ce stade, le programme espion modifie plusieurs fichiers de configuration situés dans le répertoire /private/var/root/Library/Preferences/. D’abord com.apple.CrashReporter.plist, pour que l’iPhone n’envoie plus de rapport d’activité à Apple. Ensuite com.apple.softwareupdateservicesd.plist pour que les mises à jour n’écrasent pas les modifications. Puis roleaccountd.plist, pour indiquer au système qu’il doit lancer au démarrage les commandes situées dans le répertoire /private/var/db/com.apple.xpc.roleaccountd.staging/.

Une méthode qui change à chaque fois consiste à ce stade à communiquer avec un serveur Pegasus pour installer dans ce répertoire les commandes qui serviront ensuite à exporter les données.

Les dernières étapes consistent à copier un interpréteur de commandes présent parmi les applications de l’appareil dans le répertoire des commandes réservées au système, à savoir /usr/libexec/, de sorte que cet interpréteur puisse exécuter des commandes avec les droits root, c’est-à-dire avec tous les droits d’accès. Les premières versions de Pegasus, copiaient en l’occurrence ici l’interpréteur jsc – celui qui sert à exécuter les javascripts – en le renommant rtbuddyd, puis l’inscrivaient dans la séquence de démarrage d’iOS avec le paramètre --early-boot. Il s’agit d’une manière de tromper un éventuel observateur : --early-boot n’est en réalité pas un paramètre mais le nom d’un fichier. En l’occurrence, il s’agit plutôt d’un lien symbolique, créé à côté de rtbuddyd dans le même répertoire /usr/libexec/ et qui pointe vers le javascript malicieux qui a déclenché la toute première infection. Exécuter ce JavaScript à chaque démarrage permet de s’assurer que les protections du système sont de nouveau désactivées à chaque fois que l’utilisateur éteint et rallume son iPhone.

Phase 3 : comment les données sont extorquées

On l’a dit : le monde Open source regorge de commandes compatibles avec iOS pour exporter des données locales vers un serveur situé ailleurs sur Internet. Toutefois, Pegasus est supposé espionner des personnes par nature méfiantes, susceptibles d’analyser l’activité de leur iPhone en consultant régulièrement le backup de leur appareil. Sur Mac, par exemple, ce backup se trouve dans le répertoire ~/Library/Application Support/MobileSync/Backup/ et il est possible de parcourir son contenu à l’aide de l’outil Open source DB Browser for SQLite. De fait, NSO a pris le parti de renommer les outils conventionnels d’extraction avec des noms qui ressemblent à s’y méprendre à des commandes de cuisine interne d’iOS, le système d’exploitation de l’iPhone.

Les processus utilisés par Pegasus s’appellent par exemple com.apple.Mappit.SnapshotService pour faire croire qu’il s’agit de com.apple.MapKit.SnapshotService ou encore ReminderIntentsUIExtension pour ressembler à RemindersIntentsUIExtension, deux dispositifs qui servent juste à assembler des éléments graphiques dans les pages.

De la même manière, l’URL du serveur vers lequel sont exportées les informations est difficilement identifiable parmi le flot des logs. Les adresses sont une succession interminable de caractères sans queue ni tête, devant un nom de domaine qui n’existe en ligne que pendant quelques heures et dont il ne reste plus dans les registres Whois de l’Internet mondial que des mentions « client Transfer prohibited » et autres « Registry Registrant ID: Not disclosed », stipulant que plus personne n’a d’information sur ces adresses et qu’il ne faut pas y toucher. Pour autant, Amnesty International remarque que NSO a obtenu pour chacun de ses serveurs des certificats SSL/TLS, a priori auprès d’autorités dites de confiance. 

Amnesty International, qui traque les indices à propos de ces adresses, note que les serveurs qui collectent les informations des victimes sont potentiellement attribués à un seul client de NSO. Tout comme les serveurs qui serviraient à injecter Pegasus dans les smartphones et qui ont encore d’autres adresses. 

Comment détecter la présence de Pegasus

Amnesty International a développé un outil, MVT (Mobile Verification Toolkit) capable de détecter les traces d’un logiciel espion dans la sauvegarde d’un iPhone ou d’un smartphone sous Android. Il se base sur un dictionnaire d’indices au format Stix2. Le dictionnaire correspondant à Pegasus, nommé pegasus.stix2 au moment de l’écriture de cet article, se télécharge depuis le Github d’AmnestyTech.

MVT nécessite pour fonctionner que le langage Python 3.6 minimum et la bibliothèque libusb soient installés sur le système qui héberge la sauvegarde. Sur Linux, ces prérequis s’installent avec la commande suivante :

$ sudo apt install python3 python3-pip libusb-1.0-0

Sur macOS, il faudra installer l’utilitaire Homebrew au préalable ; il sert à déployer sur le système tous les outils Open source habituels du monde Linux. Ensuite, la commande à taper pour installer les prérequis est :

$ brew install python3 libusb

On installe ensuite MVT avec l’utilitaire pip de Python3 :

$ pip3 install mvt

Il ne reste plus qu’à exécuter l’une des commandes possibles selon le smartphone et le système qui héberge sa sauvegarde. Par exemple, pour analyser la sauvegarde d’un iPhone depuis un Mac, il faudra taper la commande ci-dessous (sur une seule ligne) en indiquant à la suite du paramètre --iocs le chemin où se trouve le fichier pegasus.stix2 (dans cet exemple sur le bureau) et à la fin de la commande le nom du sous-répertoire qui contient la sauvegarde. Ce nom se présente sous la forme d’une longue expression en hexadécimale. Si vous venez d’effectuer cette sauvegarde, il s’agira du répertoire le plus récent. Dans cet exemple, le nom du répertoire est remplacé par « 000000 ».

$ mvt-ios check-backup --iocs ~/desktop/pegasus.stix2 ~/Library/Application\ Support/MobileSync/Backup/000000

MVT dresse la liste de tout ce qu’il parvient à analyser parmi la sauvegarde. Il n’indique pas à la fin que tout est normal. En réalité, il ne faut s’inquiéter que si l’une des lignes affichées commence par WARNING.

Pour approfondir sur MacOS