####################################################################### Luigi Auriemma Applicazione: libreria ENet http://enet.bespin.org Versioni: <= Jul 2005 (l'attuale versione su CVS) Piattaforme: Windows, *nix, *BSD ed altre Bugs: A] invalid memory access (32 bit) B] allocation abort with fragment Exploitation: remoto Data: 12 Mar 2006 Autore: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ####################################################################### 1) Introduzione 2) Bugs 3) The Code 4) Fix ####################################################################### =============== 1) Introduzione =============== ENet e' una libreria open source molto potente per la gestione delle connessioni via UDP (puo' quasi essere considerata una sorta di TCP over UDP). La libreria e' molto utilizzata in alcuni motori e giochi come Cube, Sauerbraten, Duke3d_w32 ed altri. ####################################################################### ======= 2) Bugs ======= ---------------------------------- A] invalid memory access (32 bit) ---------------------------------- ENet utilizzata dei numeri a 32 bit per quasi tutti i parametri utilizzati nei propri pacchetti, come offsets dei frammenti, grandezza dei dati, timestamps, challenge numbers e cosi' via. Ogni pacchetto ricevuto dalla libreria (enet_host_service) e' gestito dalla funzione enet_protocol_handle_incoming_commands. Questa funzione utilizza un puntatore (currentData) che punta al comando corrente, ogni paccheto puo' contenere uno o piu' comandi che descrivono operazioni come una richiesta di connessione, un acknowledge, un frammento, un message ed altro. L'istruzione che controlla questo puntatore per evitare che punti oltre il pacchetto ricevuto puo' essere elusa attraverso un parametro header.commandLength molto grande (negativo sulle CPU a 32 bit). Dopo aver bypassato il controllo currentData puntera' ad una zona di memoria invalida e quando il ciclo passera' al comando successivo (commandCount deve essere maggiore di uno) l'applicazione crashera'. I processori a 64 bit non dovrebbero essere vulnerabili. Da enet_protocol_handle_incoming_commands in protocol.c: ... currentData = host -> receivedData + sizeof (ENetProtocolHeader); while (commandCount > 0 && currentData < & host -> receivedData [host -> receivedDataLength]) { command = (ENetProtocol *) currentData; if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength]) return 0; command -> header.commandLength = ENET_NET_TO_HOST_32 (command -> header.commandLength); if (currentData + command -> header.commandLength > & host -> receivedData [host -> receivedDataLength]) return 0; -- commandCount; currentData += command -> header.commandLength; ... --------------------------------- B] allocation abort with fragment --------------------------------- ENet supporta anche la gestione dei frammenti usati per costruire i messaggi piu' grandi dell'MTU del ricevente. Quando viene ricevuto un frammento la libreria alloca la grandezza totale del messaggio in memoria in modo da poter ricostruire abbastanza facilmente i successivi frammenti in questo buffer. Ma se la grandezza totale dei dati specificata dall'attacker non puo' essere allocata (perche' eccessiva) la libreria chiama abort() e tutto il programma termina. Da enet_protocol_handle_send_fragment in protocol.c: ... startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE), fragmentCount); ####################################################################### =========== 3) The Code =========== http://aluigi.org/poc/enetx.zip ####################################################################### ====== 4) Fix ====== No fix. Nessuna risposta dagli sviluppatori. #######################################################################