Im Smartcard-Support von Qemu ist eine Sicherheitslücke entdeckt worden, die es einem lokalen Angreifer erlaubt, höhere Rechte zu erlangen und Denial-of-Service-Attacken durchzuführen.
Die Schwachstelle befindet sich in der Implementierung des Passthru-Protokolls, welches über VSCard (Virtual Smart Card Protocol) realisiert ist. Dieses Protokoll stellt verschiedene Nachrichten-Typen bereit, die in der Aufzählung “VSCMsgType” definiert sind:
typedef enum { VSC_Init = 1, VSC_Error, VSC_ReaderAdd, VSC_ReaderRemove, VSC_ATR, VSC_CardRemove, VSC_APDU, VSC_Flush, VSC_FlushComplete
} VSCMsgType;
Ein Programmierfehler hat sich beim Verarbeiten von “VCS_ATR”-Nachrichten in den Qemu-Code eingeschlichen. Diese Nachrichten haben den
folgenden einfachen Aufbau:
/* VSCMsgATR Client -> Host * Answer to reset. Sent for card insertion or card reset. The reset/insertion * happens on the client side, they do not require any action from the host. * */
typedef struct VSCMsgATR { uint8_t atr[0];
} VSCMsgATR;
Sie signalisieren einen Karten-Reset oder das Einsetzen einer Smartcard. Die zentrale Funktion zum Behandeln der verschiedenen Nachrichten ist in der Datei “/hw/ccid-card-passthru.c” untergebracht. Die folgende Funktion filtert die verschiedenen Nachrichten mit Hilfe eines größeren Switch-Blocks:
static void ccid_card_vscard_handle_message(PassthruState *card, VSCMsgHeader *scr_msg_header)
Der Case-Block für “VSC_ATR”-Nachrichten sieht folgendermaßen aus:
case VSC_ATR: DPRINTF(card, D_INFO, "VSC_ATR %d\n", scr_msg_header->length); if (scr_msg_header->length > MAX_ATR_SIZE) { error_report("ATR size exceeds spec, ignoring"); ccid_card_vscard_send_error(card, scr_msg_header->reader_id, VSC_GENERAL_ERROR); } memcpy(card->atr, data, scr_msg_header->length); card->atr_length = scr_msg_header->length; ccid_card_card_inserted(&card->base); ccid_card_vscard_send_error(card, scr_msg_header->reader_id, VSC_SUCCESS); break;
Die erste If-Abfrage stellt sicher, dass die Länger von “scr_msg_header” nicht größer ist als “MAX_ATR_SIZE”. Diese Abfrage ist wichtig, da später dieser Längeneintrag von “memcpy()” verwendet wird, um Speicher genau dieser Länge zu kopieren.
Wer genau hinsieht entdeckt in diesen Codezeilen einen kleinen Flüchtigkeitsfehler: Die If-Abfrage sendet zwar im Fehlerfall eine “VSC_GENERAL_ERROR”-Nachricht, aber sie bricht nicht via “break() aus”. Das heißt, auch wenn “scr_msg_header->length” größer als “MAX_ATR_SIZE” ist, wird die anschließende “memcpy()”-Funktion aufgerufen. Der Angreifer kann damit unberechtigt andere Speicherbereiche des Programms manipulieren und so unter Umständen sogar seine eigenen Befehle ausführen. Die Korrektur dieses Programmierfehlers besteht natürlich darin, einfach am Ende der If-Anweisung ein “break()” einzufügen.
Betroffen sind die Qemu-Versionen vor 1.0.

