Axi0mx a publié checkm8, qui permet d’exploiter un bug dans la SecureROM de l’iPhone 4S à l’iPhone X. Ce bug ne peut pas être corrigé.

SecureROM

La SecureROM (aussi appelée BootROM) est le premier composant à démarrer. Elle va démarrer le CPU, l’horloge, la RAM etc…

Ce bootloader va aussi initialiser le hardware de l’iPhone : composants USB, SPI, PCI.

Elle a la particularité d’être en lecture seule (ROM = Read Only Memory) donc il n’est pas possible de mettre à jour son code.

Il y a deux méthodes de démarrage pour la BootROM :

  • normal, qui va démarrer les bootloaders suivants pour charger le kernel
  • DFU (Device Firmware Upgrade) ce mode va permettre d’accepter d’une image iBSS (équivalent du LLB pour le démarrage par défaut) envoyée via USB.

                    NAND/Normal  +------+     +-------+
                   ------------> | LLB  | --> | iBoot | --> iOS
    +-----------+ /              +------+     +-------+
    | SecureROM |<
    +-----------+ \              +------+     +-------+
                   ------------> | iBSS | --> | iBEC  | --> Restore
                    USB/DFU      +------+     +-------+

Le mode DFU est la partie de la BootROM qui contient le plus de bugs. La majorité des exploits BootROM sont liés au mode DFU. C’est dans cette partie du code qu’à été découverte la faille exploitée par checkm8

checkm8

Axi0mx a annoncé l’exploit jeudi dernier. Celui est compatible à partir de l’iPhone 4S jusqu’à l’iPhone X (A5 -> A11).

Le dernier exploit de ce type a publié par axi0mx en 2017 pour les iPhone 3GS. Avant ça l’exploit BootROM le plus récent était Limera1n pour l’iPhone 4 publié en 2010.

La particularité des failles dans la BootROM est qu’elles ne peuvent pas être corrigées via une mise à jour logicielle. Donc checkm8 est compatible avec tous les appareils du 4S au X pour toutes les versions, même celles à venir. De plus ce bug permet le niveau de privilèges le plus élevé possible.

Pour exploiter ce bug il faut obligatoirement avoir l’appareil en main et le brancher à un ordinateur. On ne peux donc pas exploiter cette faille à distance.

Heureusement, celui-ci comprend uniquement le SecureROM et non le SEP qui protège les données personnelles des idevices. Le SEP a son propre SOC qui n’a pas encore été compromis publiquement donc les données sensible restent en sécurité pour l’instant.

Le bug

  1. En mode DFU, lorsque l’interface USB démarre pour obtenir une image, elle va enregistrer une interface permettant de gérer toutes les commandes et allouer un buffer pour les I/O.
  2. Si vous envoyez des données, le paquet d’installation est traité par le code principal qui appelle ensuite le code de l’interface USB.
  3. Le code d’interface vérifie que wLength est plus court que la longueur du buffer de sortie en entrée et, le cas échéant, il met à jour un pointeur passé en argument avec un pointeur sur le tampon de sortie
  4. Il retourne ensuite la variable wLength qui est la longueur qu’il veut recevoir dans le buffer
  5. Le code du driver USB met ensuite à jour une variable globale avec la longueur et se prépare à recevoir les paquets de données.
  6. Si un paquet de données est reçu, il est écrit dans le io_buffer via le pointeur qui a été passé sous forme d’argument et une autre variable globale est utilisée pour suivre le nombre d’octets déjà reçus.
  7. Quand toutes les données ont été reçues, le code spécifique au mode DFU est appelé à nouveau, puis le contenu du io_buffer est copié dans l’emplacement mémoire où l’image est ensuite démarrée.
  8. Ensuite le code USB réinitialise toutes les variables et continue à gérer les nouveaux paquets.
  9. Si l’iPhone sort du mode DFU, le io_buffer est libéré et en cas d’échec de l’analyse de l’image, la BootROM entre à nouveau en DFU.

Le problème est que si on envoie aucune donnée via USB, la BootROM va déclencher une réinitialisation USB et quand même tenter d’analyser une image qui n’existe pas. Si le parsing de l’image échoue, la BootROM redémarre en mode DFU. Cependant l’étape 8 n’est pas effectuée et les variables globales contiennent encore leur valeurs. L’étape 9 est quand même exécutée et io_buffer est libéré. Mais le pointeur qui a été passé comme argument pointe toujours sur le buffer.

Donc on peut écrire vers le buffer qui a été libérée en envoyant des paquets vers l’appareil.

Avec iOS 12, lorsque l’appareil rentre à nouveau en DFU, le contenu des variables globales dans la fonction usb_core_init() sont effacées.

La faille étant présente dans la stack USB et celle-ci étant réinitialisée à chaque redémarrage, il n’est pas possible de faire persister l’exploit.

ipwndfu

ipwndfu a été publié en 2017, avec alloc8 (allocate), un exploit BootROM pour les iPhone 3GS dits new BootROM qui n’étaient pas compatible avec le dernier exploit persistent 24kpwn.

Actuellement avec ipwndfu et checkm8 on peut :

  • passer en pwnedDFU pour autoriser l’iPhone à charger des images non-signées.
  • dump de la SecureROM
  • récupération des clés pour déchiffrer les bootloaders
  • demotion des appareils pour permettre de faire du debugging de bas niveau à l’aide de JTAG.

D’ici les prochaines semaines les possibilités de checkm8 seront accrues :

  • Jailbreak
  • Dual-Boot
  • Installation d’un OS tiers (Linux, Android, Windows on ARM)

Bonobo

La société LambdaConcept en a profité pour publier un article sur un câble SWD fait maison utilisant OpenOCD nommé: Bonobo.

Pour fonctionner ce câble a besoin que l’appareil soit demoté. Cela signifie que l’on peut activer le debugging avec JTAG sur les appareils de production. Et par chance, ipwndfu permet ça, comme on l’a vu plus haut (super timing).


Axi0mx a découvert le bug de checkm8 grâce au patch diffing (ou bindiffing), qui consiste à analyser deux fichiers binaires pour trouver les différences. Mais il n’est pas le seul à avoir découvert cette faille. littlelailo l’a aussi découverte en faisant de l’analyse statique de binaire.

Il semble aussi que ce bug était connu depuis au moins janvier 2018 d’après ce tweet.


ressources :