1 – Vulnérabilité dans le contrôleur virtuel de disquettes de QEMU

Résumé

Le 15 mai 2015, une entreprise spécialisée en sécurité a publié les détails sur une vulnérabilité impactant le logiciel QEMU et pouvant être exploitée pour obtenir, depuis une machine virtuelle invitée, une exécution de code arbitraire sur la machine hôte.

Cette vulnérabilité, identifiée sous la référence CVE-2015-3456, porte sur l’implémentation du contrôleur de disquettes de QEMU et touche plusieurs logiciels de virtualisation tels que Virtualbox, Xen ou KVM.

Analyse

Cette vulnérabilité est causée par un débordement de tampon rendu possible par un contrôle défaillant lors de l’écriture dans le tampon de données FIFO du contrôleur.

Le contrôleur virtuel de disquettes, à l’instar des contrôleurs physiques, est commandé par l’écriture de commandes dans le port d’entrée/sortie FIFO. Ce port est accessible en lecture et en écriture (fonctions standards inb() et outb()).

Structures de données

Le lecteur virtuel de disquettes est défini par la structure FDrive dans le fichier hw/block/fdc.c. Le membre fdctrl permet de remonter à la définition de la structure du contrôleur plus loin dans le même fichier :

struct FDCtrl {
    […]
    /* Command FIFO */
    uint8_t *fifo;
    int32_t fifo_size;
    uint32_t data_pos;
    uint32_t data_len;
    uint8_t data_state;
    uint8_t data_dir;
    […]
};

La taille du tampon FDCtrl->fifo est fixée à 512 octets lors de l’initialisation du contrôleur.

Le champ FDCtrl->data_len désigne le nombre de paramètres acceptés par la commande et le champ FDCtrl->data_pos représente le nombre d’octets effectivement reçus par le contrôleur.

Ces deux paramètres sont définis au même endroit que les fonctions de prise en charge des commandes.

Déclenchement

L’écriture dans ce tampon est réalisée par la fonction fdctrl_write_data, et est soumise à la vérification du champ FDCtrl->data_pos. Ce champ est normalement réinitialisé lors de la fin d’exécution du gestionnaire de commande. Toutefois, lors de l’usage d’une des deux commandes DRIVE_SPECIFICATION ou READ_ID, la réinitialisation de ce champ peut être retardée voire même contournée.

Ainsi, lors de l’utilisation de la commande DRIVE_SPECIFICATION, il est possible d’incrémenter la valeur de FDCtrl->data_pos si le bit de poids fort du 5ème paramètre est nul.

Le code s’exécutant dans la machine virtuelle peut donc écrire des données arbitraires dans l’espace mémoire du processus Qemu s’exécutant sur la machine hôte.

Une utilisation de GDB nous permet de vérifier l’état de la mémoire correspondante après une exploitation.

 gdb$ x/132x *(&(fdctrl->fifo))
0x555557850000: 0x4141418e 0x42424200 0x20202020 0x20202020
0x555557850010: 0x20202020 0x20202020 0x20202020 0x20202020
*
0x5555578501f0: 0x20202020 0x20202020 0x20202020 0x20202020 # fin de FDC->fifo
0x555557850200: 0x6a6e6f42 0x5372756f 0x69637561 0x21657373 # donnees ecrasees

Recommandations

Le CERT-FR recommande l’application des correctifs de sécurité fournis par les éditeurs concernés dès que possible.

Documentation

Rappel des avis émis

Dans la période du 01 au 07 juin 2015, le CERT-FR a émis les publications suivantes :