Posts Blackbird : faille dans l'enclave sécurisée de l'iPhone
Post
Cancel

Blackbird : faille dans l'enclave sécurisée de l'iPhone

Dans ce post on va parler d’une faille dans l’enclave sécurisée de l’iPhone : Blackbird. Cette faille est située dans la mémoire ROM du SEP, et ne peut donc pas être corrigée. Le titre mentionne de l’iPhone, mais cette faille touche aussi les iPads, iPod touches et les Macs avec un puce T2.

Secure Enclave Processor

Le Secure Enclave Processor (SEP) est un coprocesseur embarqué dans les appareils iOS d’Apple depuis l’iPhone 5S. Il a pour but de stocker et chiffrer les données biométriques utilisées par Face ID et Touch ID, ainsi que les données bancaires pour Apple Pay.

Depuis 2018 le SEP est aussi intégré dans les Macs avec une puce T2 ainsi que les nouveaux Macs avec un processeur Apple Silicon.

Cette enclave reprend le concept ARM de TrustZone et d’exécution d’environnement fiable. En plus d’avoir son propre système d’exploitation comprenant un kernel et des applications dédiées, le SEP possède aussi ses propres périphériques, comme un moteur de chiffrement, un générateur de nombres aléatoires matériel matériel (True Random Number Generator) ainsi qu’un CPU dédié.

Le Secure Enclave Processor étant indépendant de l’Application Processor (AP), il n’est pas impacté par la faille checkm8. Les données qu’il protège ne peuvent pas être déchiffrées.

Checkm8

En septembre 2019, axi0mx a dévoilé checkm8. C’est une faille dans la stack USB de la SecureROM qui permet de prendre le contrôle de la chaine de démarrage iOS et de charger une nouvelle image non-autorisée par Apple. Etant basée dans une mémoire de type read-only, cette faille ne peut pas être corrigée avec une mise à jour logicielle.

Checkm8 doit être exploitée avec le mode DFU. Le mode DFU permet de transférer via USB des images de démarrage iOS pour mettre à jour ou restaurer un iPhone.

Un nouvel outil de jailbreak basé sur cette faille a été publié : checkra1n.

iOS 14

Avec l’arrivée d’iOS 14, il y a eu certains changements dans le firmware du SEP pour les appareils avec une puce A10, A10X et A11. Apple a inséré du code au début du firmware (0x0 - 0x10000). Ce code, qu’on appellera “boot code” semble avoir 3 choses à faire :

Lorsqu’un appareil iOS démarre en mode DFU ou Recovery, la SEPROM demande au TRNG de générer un nonce. La valeur du registre d’entropie de la SEPROM sera ainsi différente que lorsqu’il démarre normalement.

Si la valeur du registre est différente de celle attendue par le “boot code”, alors il ajoute la valeur 1 dans le registre nommé Boot Progress Register (BPR).

Ce registre est ensuite lu par le kernel de SEPOS. Si le BPR est activé, alors le kernel va verrouiller le bit d’amorçage du mot de passe de l’iPhone. Si ce bit d’amorçage est verrouillé, les données de l’iPhone ne peuvent plus être déchiffrées. Seul un redémarrage permettra de réinitialiser ce bit.

Lorsque l’application du SEP Secure Key Store va recevoir la requête de déchiffrement des données, elle va retourner une erreur qui va faire paniquer SEPOS, produisant un kernel panic du noyau iOS.

L’objectif de cette nouvelle protection est de bloquer les jailbreaks basés sur une faille exploitant le mode DFU et Recovery.

TZ0

Le SEP des anciens appareils ne possède que 4096 octets de RAM. Cette RAM est dédiée à l’initialisation de variables et de la stack du SEP, il lui faut donc plus de RAM pour charger et démarrer SEPOS et ses applications.

L’iBoot, le bootloader du Processeur Applicatif (AP), va configurer une zone mémoire de l’AP qui sera réservée au SEP, on appelle cette zone TZ0. Cette zone mémoire externe au SEP sera inaccessible à l’AP grâce au contrôleur de mémoire (AMCC). Elle sera aussi chiffrée par la SEPROM.

Ci-dessus on peut voir le code de l’iBoot décompilé qui configure TZ0.

Lorsque la zone mémoire est configurée, l’iBoot envoie un Ping à la SEPROM qui à son tour renvoie un ACK. L’iBoot peut ensuite envoyer la commande BootTZ0 pour demander à la SEPROM de mapper son espace d’adressage dans la zone mémoire TZ0 et ainsi chiffrer cette partie de la mémoire.

Bien sûr, la SEPROM va vérifier si TZ0 est bien verrouillée avant de chiffrer la mémoire. Les valeurs de TZ0_base et TZ0_end qui désignent début et la fin de TZ0 seront stockées dans 2 registres. Ces registres sont partagés par l’AP et le SEP.

Blackbird

Blackbird est le nom donné à une faille dans la ROM dédiée au SEP (SEPROM). Cette faille permet à l’enclave d’utiliser une mémoire non-protégée donc accessible par l’AP. Elle a été découverte indépendamment par windkown et littlelailo.

Le SEP étant un processeur KingFisher 32 bits, les registres pour stocker les valeurs de TZ0 sont donc de 32 bits.

Apple a choisi de convertir les adresses TZ0_start et TZ0_end par un décalage de 12 bits pour que la mémoire du SEP puisse être adressée par un registre de 32 bits.

Cela signifie que pour verrouiller les zones mémoire 0x1000000 ~ 0x2000000 il faut que l’iBoot écrive dans les registres TZ0_base et TZ0_end les valeurs 0x1000 et 0x2000.

Lors de l’étape de démarrage, après que l’iBoot ai initialisé la zone mémoire TZ0, on peut voir ci-dessous que la SEPROM démarre TZ0 et renvoie un ACK à l’iBoot. Si tout est OK la SEPROM charge SEPOS.

C’est dans la fonction BootTZ0, que la SEPROM va charger les valeurs lues dans les registres, puis elle décalera ces valeurs de 12 bits. Donc on passe de 0x1000 à 0x1000000.

Comme le note Lailo dans son writeup, c’est un problème majeur, car le SEP étant un processeur 32 bits si on utilise une adresse assez haute on va dépasser la taille d’un entier non-signé de 32 bits.

Par défaut pour la puce A10, la valeur de TZ0_base est 0x7d200 et la valeur de TZ0_end est 0x7ddff. Si on spécifie que la zone mémoire TZ0 se trouve à TZ0_base + 0x100000 et que l’on fait pareil pour TZ0_end, la SEPROM va décaler les adresses de 12 bits. On se retrouve avec une zone mémoire 0x17d200000 ~ 0x17ddff000. Cela va déplacer les bits 20 et supérieurs en dehors du registre. Par ce débordement le SEP utilisera une zone mémoire non protégée par le contrôleur de mémoire.

Cette faille est en théorie présente sur les puces A8 - A12, mais elle n’offre pas les mêmes possibilités sur tous les appareils. De plus il faut obligatoirement pouvoir exécuter du code arbitraire dans l’iBoot pour changer l’adresse de la Trust Zone. Pour le moment, seule checkm8 permet de ça.

Littlelailo a donné le nom de Blackbird à cette faille en référence a l’avion espion construit pour voler tellement haut dans le ciel qu’il n’était pas détecté par les radars.

Checkra1n

Quelques semaines après la sortie officielle d’iOS 14.0, une nouvelle version de l’outil de jailbreak Checkra1n a été publiée. Cette version comporte une implémentation de l’exploit pour Blackbird et permet de charger un sep-firmware modifié.

L’exploit est embarqué dans PongoOS, un mini OS développé exprès pour Checkra1n. PongoOS est chargé par l’iBoot et permet d’appliquer les patches nécessaires au kernel d’iOS, mais aussi de démarrer Linux ou Android comme expliqué dans un précédent post.

Actuellement, l’exploit implémenté par Checkra1n est utilisé pour patcher la vérification du Boot Progress Register. Comme vous pouvez le voir ci-dessous, PongoOS exécute l’exploit, patch le BPR et prépare le payload pour qu’il soit démarré.

Tout se passe dans la fonction seprom_fwload_race. Cette fonction permet de charger un firmware modifié.

La première partie de la fonction configure le conteneur IMG4 pour le firmware du SEP, puis prépare le shellcode à injecter.

La fonction elle initialise les registres de TZ0, et map la zone mémoire qui sera utilisée par le SEP.

1
2
3
4
5
6
7
8
9
10
11
12
13
volatile uint32_t *tz_regbase = TZ_REGS;
uint32_t tz0_size = (((uint64_t)tz_regbase[1]) << 12)-(((uint64_t)tz_regbase[0]) << 12) + (1 << 12);
uint64_t tz0_base = (((uint64_t)tz_regbase[0]) << 12);
map_range(0xc00000000, 0x800000000 + tz0_base, tz0_size, 3, 2, true);

// Set TZ0 regbase to 0x100000.
if (!tz_blackbird()) goto out;

tz_lockdown();

seprom_ping();
seprom_boot_tz0();
seprom_ping();

L’extrait de code ci-dessus montre l’initialisation de Blackbird par PongoOS.

Comme on l’a vu plus précédemment, c’est normalement à l’iBoot de configurer la Trust Zone. On peut imaginer que l’équipe de Checkra1n a patché l’iBoot pour qu’il passe l’étape de configuration de TZ0 pour la laisser à PongoOS.

La fonction tz_blackbird() sert à configurer l’adresse de base de TZ0 à 0x100000. La suite du code fait exactement comme aurait dû le faire l’iBoot : verrouillage de la zone mémoire, envoi d’un ping à la SEPROM, puis demande lui SEPROM de démarrer TZ0.

La reste de la fonction va permettre de charger SEPOS avec le patch pour ignorer la vérification du Boot Progress Register.

Pour l’instant, l’exploit fonctionne pour les appareils avec une puce A10, A10X et T2. L’exploit n’a pas été implémenté pour les précédentes générations car c’est inutile pour le bon fonctionnement de Checkra1n.

Pour ce qui est de la puce A11, la SEPROM dispose d’une protection qu’on appelle un integrity tree pour empêcher les replay attacks comme celle utilisée dans cet exploit. L’exploit ne fonctionne pour appareils pour les appareils équipés d’une puce A11.

Je n’ai pas voulu m’attarder sur Checkra1n car Siguza, l’un des développeurs de Checkra1n a annoncé qu’il publierait un billet de blog sur l’implementation de Blackbird avec Checkra1n.


Pour conclure, on a un bug très intéressant qui permet de prendre le contrôle de SEPOS. Néanmoins l’exploitation est limitée aux puces A8 - A10. En effet, la faille peut être uniquement utilisée si vous avez déjà le contrôle sur l’iBoot ou la SecureROM. Donc un accès physique à l’appareil sera nécessaire pour exploiter cette faille.

Actuellement, l’exploit de Checkra1n est utilisé pour patcher la vérification du BPR, mais il est aussi possible de désactiver le compteur du nombre d’essais de mots de passe de déverrouillage. Cela permettrait de tester des mots de passe à l’infini, par exemple via une attaque par force brute.


Sources :

This post is licensed under CC BY 4.0 by the author.