Dans ce post je vais faire faire une analyse des composants logiciel du Secure Enclave Processor (SEP).

A propos du SEP

Ce composant de l’iPhone a pour but de stocker les informations critiques comme le code dévérouillage de l’iPhone, les empreintes digitales qui sont aussi utilisées pour dévérrouiller l’iPhone, ainsi que Apple Pay pour les nouvelles générations d’iBidules.

Le SEP a été introduit avec l’arrivée du premier iPhone 64 bits : l’iPhone 5S. Aujourd’hui on le trouve même sur les nouveaux MacBooks Pro avec la Touchbar et Touch ID.
t1

Jusqu’à hier, le SEP était une black box inaccessible. Il semble que la sécurité par l’obscurité ai marchée pendant pas mal de temps.

Dechiffrer le firmware SEP

Jusque là, il était alors impossible d’acceder aux différents composants du SEP, car contrairement au kernelcache aux logos au demarrage, Apple chiffre encore cette image.

Mais il y a quelques jours (16/08/2017), xerub a publié la clé et l’IV pour déchiffrer le firmware du SEP pour iPhone 5S. Il est desormais possible d’analyser le SEPOS plus en profondeur.

Pour déchiffrer le firmware du Secure Enclave il faut quelques pré-requis :

  • img4tool
  • sepsplit
  • La clé + l’IV

Tout d’abord veuillez installer img4tool :

$ git clone https://github.com/xerub/img4tool && cd img4tool
Cloning into 'img4tool'...
remote: Counting objects: 42, done.
remote: Total 42 (delta 0), reused 0 (delta 0), pack-reused 42
Unpacking objects: 100% (42/42), done.
Checking connectivity... done.
$ git submodule init && git submodule update
Submodule 'lzfse' (https://github.com/lzfse/lzfse) registered for path 'lzfse'
$ make -C lzfse && make
make: Entering directory '/home/mathieu/Documents/img4tool/lzfse'
cc -Os -Wall -Wno-unknown-pragmas -Wno-unused-variable -DNDEBUG -D_POSIX_C_SOURCE -std=c99 -fvisibility=hidden -c src/lzfse_encode.c -o build/obj/lzfse_encode.o 
[...]
gcc -o img4 -m64 -g -Llzfse/build/bin libDER/DER_Decode.o libDER/oids.o img4.o -llzfse -lcrypto

Ensuite vous clonez puis compilez sepsplit

$  git clone https://gist.github.com/xerub/0161aacd7258d31c6a27584f90fa2e8c sepsplit
Cloning into 'sepsplit'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Unpacking objects: 100% (3/3), done.
Checking connectivity... done.
$ cd sepsplit && gcc sepsplit.c -o secplit

Pour la clé et l’IV vous pouvez chopper ça sur The iPhone Wiki.

Bien maintenant qu’on a tout on peut commencer par déchiffrer l’image du firmware avec img4tool.

$ img4 -i sep-firmware.n51.RELEASE.im4p sep-firmware.n51.RELEASE.im4p.dec b370c7d85476823ef83d3991cb8078b954c3a8ffe7f2437ea23c4c7ea72a66544644b869849e4635dfbf74824a61a733
sepi

Voilà on a fait la moitié du travail on peut voir la différence rien qu’avec la commande file.

$ file sep-firmware.n51.RELEASE.im4p
sep-firmware.n51.RELEASE.im4p: data
$ file sep-firmware.n51.RELEASE.im4p.dec
sep-firmware.n51.RELEASE.im4p.dec: PCX ver. 2.5 image data bounding box [65534, 60159] - [65534, 60159], 234-bit uncompressed

Maintenant il va donc falloir séparer les composants pour une meilleure ananlyse en utilisant sepsplit compilé un peu plus tôt.

$ sepsplit sep-firmware.n51.RELEASE.im4p.dec
boot
kernel
SEPOS        phys 0x83000, virt 0x7000, size 0x1a000, entry 0xad84
SEPDrivers   phys 0x9d000, virt 0x8000, size 0x1f000, entry 0xcf90
sepServices  phys 0xbc000, virt 0x8000, size 0x1b000, entry 0x15f90
ARTManager   phys 0xd7000, virt 0x8000, size 0x10000, entry 0xff78
sks          phys 0xe7000, virt 0x8000, size 0x92000, entry 0x2f910
sbio         phys 0x179000, virt 0x1000, size 0x2ea000, entry 0x750fc
scrd         phys 0x463000, virt 0x1000, size 0x2d000, entry 0x13074

Et voilà ! Nous avons donc un firmware déchiffré avec le composants séparés pour une meilleure analyse.

Hardware

Le SEP est un processeur ARMv7a, nom de code “Kingfisher”, avec une architecture 32 bits. Celui-ci tourne avec son propre système d’exploitation : SEPOS.
Tous les composants de ce processeur sont rassemblés dans une image de type img4 dans le firmware de tous les appareils 64 bits d’Apple (sauf les Macs sans touchbar).

Le SEP à ses propres périphériques (Crypto Engine, Generateur de nombres alétoires, etc…) ainsi que ses propres entrées et sorties hardware (GPIO, UART, etc…).

Le circuit est conçu pour que le SEP ne puisse pas communiquer directement avec l’Application Processor de l’iPhone.

Le SEP a son propre OS dédié : SEPOS. Celui-ci inclut un noyau, un bootloader, des drivers, services ainsi que des applications (mais pas avec les petites icones).

Comme le SEP a besoin de plus de RAM que les 4096 octets de SRAM, il doit partager de la mémoire externe mais en chiffrant celle-ci pour prévenir les attaques sur la mémoire physique contre les SoC de RAM.

schema

Le schéma ci-dessus représente l’architecture de sécurité d’iOS

SEPOS

Pour ce post on va utiliser le firmware du SEP pour iPhone 5S d’iOS 10.3.3 qui est à ce jour la dernière version publique d’iOS. C’est aussi le seul firmware que l’on peut déchiffrer publiquement.

Tout d’abord SEPOS est un système d’exploitation à lui tout seul, il a son propre kernel et sont propre chargeur d’armorçage (booloader) et ses propres drivers et applications. Il est totalement différent d’iOS seposvers

Le SEPOS est composé de différents éléments :

  • sepdump00_boot
  • sepdump01_kernel
  • sepdump02_SEPOS
  • sepdump03_SEPDrivers
  • sepdump04_sepServices
  • sepdump05_ARTManager
  • sepdump06_sks
  • sepdump07_sbio
  • sepdump08_scrd

Voici un schéma bien illustré provenant d’un talk à la Black Hat sur le SEP

sepshit

Tous ces éléments exepté sepdump00_boot sont des Mach-O 32 bits compilés pour les architecture ARMv7.

$ file sepdump01_kernel
sepdump01_kernel: Mach-O arm_v7 executable

Kernel

Voici la version du kernel

sepver

Comme vous le voyez et en cherchant un peu, on peut imaginer que le noyau de SEPOS est basé sur un microkernel L4, et bien c’est le cas !

Le kernel est un fork de L4Ka::Pistachio nommé Darbat/L4-embedded avec des modifications de la part d’Apple pour qu’il tourne sur leurs appareils.
Celui-ci fourni un minimum d’interfaces, car le reste est implementé en userland.

Le rôle du noyau est très basique, il va tout d’abord initialiser la Page Table puis les interfaces de celle-ci.
Comme tout bon noyau il demarre le timer et configure le scheduler. Son dernier rôle étant de demarrer la root task qui est litteralement SEPOS.

Bien sur il a des appels système (syscalls). Il y a deux types d’appels : privilegiés et non-privilegiés. Seul le SEPOS peut invoquer les appels privilegiés en determinant l’espace d’adresse de l’appelant.

Plus d’info sur ce kernel : Il n’est pas en mode debug; ce qui est normal pour un appareil de production ohnodebug

SEPOS (root task)

La root task est le processus initial du système d’exploitation, c’est celui avec les privilèges les plus hauts. Comme dit plus haut, c’est le seul à pouvoir invoquer des syscalls privilégiés.
Le process va lire dans la liste des applications du firmware puis va initaliser tous les processus listés dans celui-ci.

La liste des applications (Application List) inclut des informations sur les différents services et apps :

  • Adresse physique
  • Adresse de base virtuelle
  • Taille du module
  • Point d’entrée.

Comme ceci :

SEPOS        phys 0x83000, virt 0x7000, size 0x1a000, entry 0xad84
SEPDrivers   phys 0x9d000, virt 0x8000, size 0x1f000, entry 0xcf90
sepServices  phys 0xbc000, virt 0x8000, size 0x1b000, entry 0x15f90
ARTManager   phys 0xd7000, virt 0x8000, size 0x10000, entry 0xff78
sks          phys 0xe7000, virt 0x8000, size 0x92000, entry 0x2f910
sbio         phys 0x179000, virt 0x1000, size 0x2ea000, entry 0x750fc
scrd         phys 0x463000, virt 0x1000, size 0x2d000, entry 0x13074

La root task a aussi pour but d’invoquer le Bootstrap Server qui contient les princpales fonctionalités du SEPOS : exportation des methodes du système, gestion mémoire des threads et objets.
Celui-ci va aussi rendre disposible les applications en utilisant le protocole RPC via l’embedded runtime et créer de nouveaux threads.

Drivers

L’OS du SEP inclut plusieurs drivers dans sepdump03_SEPDrivers : GPIO, Power Manager, etc… On peut noter que les drivers sont accessibles aux Applications via une API, c’est surement pour celà que ceux-ci sont implémentés en userland et non en kerneland, pour éviter de les utiliser comme vecteur d’attaque.
En effet, l’API contient des fonction pour contrôler, lire et écrire dans les différents drivers.

Une fois que tous les drivers ont été initialisés, ceux-ci demarrent leur propre boucle de travail pour leur registres. Ensuite le service SEPD va traduire les noms des drivers en identifiant de Thread (thread ID).
L’un des drivers principaux est AKF (Endpoint management) qui interragit avec la mailbox dont je parle un peu plus bas.

Services

sepServices, tout comme SEPDrivers sont hebergé par leur propre application. Chaque service embarqué dans l’image se défini en temps que serveur pour effectuer une tache précise.
Au demarrage, serServices s’enregistre lui-même via le bootstrap server en temps que service : sepS. Puis il créé un nouveau thread avec une boucle de travail (workloop) associée à chaque service (du coup server) qu’il va implementer.
Comme Apple fait bien les choses, dans la bibliothèque libSEPOS il y a une API pour faire tout ce travail.

Applications

On passe donc maintenant aux applications embarquées dans le firmware, quand je dis “application[s]” considérez ça comme des petits logiciels et non des apps avec des icones que vous lancez comme sur un iPhone.

  • ARTManager, Anti-replay token (ART) manager, est une app qui permet d’empecher de rejouer une token déjà utilisée (si j’ai bien tout compris), dans le white paper que j’utilise pour me renseigner, il est indiqué que le nom de l’app à changé car le Counter Service a été remplacé par l’Anti-replay Service à partir de l’iPhone 6S.

  • sks : Secure Key Store est l’application qui implémente des méthodes qui étaient précédement dans une extension du noyau (kext) : AppleKeyStore. Cela empeche l’accès aux structures de données du client SEP en passant par ces méthodes.

  • sbio : Secure Biometric Engine c’est l’application qui s’occupe de vos empreinte digitales

  • scrd : Secure Credential Manager est l’app qui implemente la methode user client dont on avait accès via AppleCredentialManager.kext. Tout comme sks, cela empeche l’accès aux structures de données du client SEP en passant par ces méthodes qui ne sont plus disponible publiquement.

  • sse : SEP secure element, cette application n’est pas disponible avec le SEPOS de l’iPhone 5S, car celui-ci n’embarque pas de puce NFC permettant d’utiliser Apple Pay, mais en gros c’est application qui fait les demandes au SEP pour payer, si l’empreinte est correcte.

mailbox

La mailbox est l’outil logiciel implémenté pour permettre aux SEP et au noyau iOS d’envoyer et recevoir des données entre eux.

iOS n’ayant aucun accès au SEPOS, il communique via un mechnanisme nommé la mailbox. C’est donc la mailbox qui autorise l’AP à communiquer avec le SEP.

C’est-à-dire, si un driver du noyau iOS doit communiquer avec un periphérique materiel ou logiciel, il envoie un message à la mailbox qui va le traiter.

C’est en fait une région de la mémoire qui est partagée entre l’AP et le Secure Enclave. Et elle est implémentée par une extention du noyaux d’iOS : AppleA7IOP .

Vous pouvez dump les kexts en utilisant joker comme ceci :

$ joker -k kernel | grep AppleA7IOP
0xfffffff0061e0a80: AppleA7IOP (com.apple.driver.AppleA7IOP)
Got 179 kexts

Puis extraire celle dont on a besoin

$ joker -K com.apple.driver.AppleA7IOP kernel
This is a 64-bit kernel from iOS 10.x (b7+), or later (3789.70.16.0.0)
ARM64 Exception Vector is at file offset @0x7f000 (Addr: 0xfffffff007083000)
Found com.apple.driver.AppleA7IOP at load address: fffffff0061e0a80, offset: 5e0a80
Writing kext out to /tmp/com.apple.driver.AppleA7IOP.kext
Workaround for Apple offset bug in the kernelcache!
Unable to resolve kernel symbol at fffffff00655736c (this is fine if it is a symbol from another kext)
Unable to resolve kernel symbol at fffffff006557390 (this is fine if it is a symbol from another kext)
Unable to resolve kernel symbol at fffffff00649ca20 (this is fine if it is a symbol from another kext)
Symbolicated stubs to /tmp/com.apple.driver.AppleA7IOP.kext.ARM64.CE3B67F2-8829-3BF6-9582-E1E2E1629B5

La kext est alors sauvegardée dans /tmp .

Vous pouvez checker l’en-tête de la kext

$ jtool -h /tmp/com.apple.driver.AppleA7IOP.kext
Magic:  64-bit Mach-O
Type:   kEXT
CPU:    ARM64
Cmds:   10
size:   1240 bytes
Flags:  0x1

En analysant la kext avec IDA on voit que celle-ci communique bien avec la mailbox.

mailbox

iPhone X

Ceci est une petite mise à jour sur l’iPhone X, en effet les firmwares ayant fuités j’ai pu me procurer celui de l’iPhone X (iPhone10,6). Grâce à joker, j’ai dumpé la kext qui communique avec la mailbox : ApplePearlSEPDriver (com.apple.driver.ApplePearlSEPDriver).

faceidk

Je n’ai pas encore récupéré beaucoup d’infos dessus, mais je compte bien continuer ma recherche grâce à certains outils comme jtool et radare:

$ jtool -h com.apple.driver.ApplePearlSEPDriver.kext
Magic:  64-bit Mach-O
Type:   kEXT
CPU:    ARM64
Cmds:   10
size:   1480 bytes
Flags:  0x1

Il se peut que le flux d’informations soit limité car il faut pour la suite que le SEP de l’iPhone X soit compromis pour permettre une plus ample analyse.

Néanmoins il est tout à fait possible de dumper le firmware du SEP sans avoir un quelquonque exploit pour celui-ci.

Securité

Apple joue de moins en moins la sécurité par l’obscurité, mais le SEP et son OS sont une exeption.

Bon tout d’abord si vous voulez vous en prendre SEP, sachez que vous aurez besoin d’un appareil 64 bits avec la possibilité d’executer du code arbitraire dans le kernel (EL1), en gros il vous faut être jailbreaké.

Logiciel

Comme surface d’attaque sur la partie logicielle il y a pas grand chose à part la mailbox et les requêtes/réponses partagées.

Etonnament l’OS n’est pas plus sécurisé que ça, puisqu”il y a peu d’exploit mitigations.

  • l’OS a été compilé avec la protection contre les Stack Cookies mais les adresses des piles sont connues et sont prévisible grâce aux threads.
  • Pas d’ASLR ou et KASLR sur l’OS pour éviter les corruptions de mémoire. Il est donc plus facile de déterminer la Kernel Base de noyau.

Ce sont 2 exemples parmis beaucoup d’autres.

BootROM

Dans la BootROM il y a deux surfaces d’attaques possibles :

  • IMG4 Parser : le parser se base sur LibDER, une bibliothèque permettant de decompresser et déchiffrer les IMG4, qui est d’ailleur utilsé dans img4tool que nous avons utilisé pour dechiffrer le firmware du SEP.
  • Hardware : corruption de mémoire en envoyant des données aux périphériques (SPI, UART, etc…) ou bien une Side-Channel Attack

Hardware

On passe à la surface d’attaque la plus amusante. Pour les appareils avec une puce A7, il est possible de tenter une Side-Channel Attack, par contre les autres appareils sont plus résistants à ce type d’attaque.

Sinon vous pouvez tenter une corruption de mémoire vers les périphériques comme :

  • SPI
  • I2C
  • UART

Malheuresement, même avec un cable DCSD il n’est pas possible d’avoir la sortie serie lors du boot du SEP/OS.

Pour conclure on voit bien que la sécurité par l’obscurité fait encore effet. De plus la séparation des privilèges diminue beaucoup les surfaces d’attaques.

Bien que l’OS ne soit pas aussi sécurisé qu’iOS il a clairement le but d’empecher quiconque d’acceder à nos données.

Bref c’est tout. N’hésitez pas à me corriger si j’ai fait une erreur ou une/des faute[s] !

Twitter : matteyeux
Github : matteyeux

sources :