####################################################################### Luigi Auriemma Applicazione: Raydium http://raydium.org Versioni: <= SVN revision 309 (versioni piu' recenti possono essere vulnerabili ad alcuni bugs non ancora corretti) Piattaforme: Windows, *nix, *BSD ed altri Bugs: A] buffer-overflow in raydium_log and raydium_console_line_add B] format string in raydium_log C] NULL function pointer in raydium_network_netcall_exec D] buffer-overflow and invalid memory access in raydium_network_read Exploitation: A] remoto, contro server e client B] remoto, contro server e client C] remoto, contro server e client D] remoto, contro client Data: 12 May 2006 Autore: Luigi Auriemma e-mail: aluigi@autistici.org web: aluigi.org ####################################################################### 1) Introduzione 2) Bugs 3) The Code 4) Fix ####################################################################### =============== 1) Introduzione =============== Raydium e' un motore di gioco molto completo e soprattutto open source. Ha supporto per il multiplayer e molte altre importanti ed interessanti caratteristiche. ####################################################################### ======= 2) Bugs ======= -------------------------------------------------------------- A] buffer-overflow in raydium_log and raydium_console_line_add -------------------------------------------------------------- La funzione di logging di Raydium e' molto utilizzata in tutto il motore. Per esempio ogni volta che un client prova ad entrare nella partita hostata dal server quest'ultimo logga l'evento nella console: raydium_log("network: client %i connected as %s"/*,inet_ntoa(from->sin_addr)*/,n,name); Questa utile funzione e' pero' vulnerabile ad un buffer-overflow dove il buffer locale str di 255 (RAYDIUM_MAX_NAME_LEN) bytes e' usato con la funzione (poco sicura) sprintf. La lunghezza del pacchetto in entrata e' di 512 (RAYDIUM_NETWORK_PACKET_SIZE) bytes dei quali 508 sono disponibili per il testo da usare per sfruttare la vulnerabilita'. Da raydium/log.c: // need to be secured void raydium_log(char *format, ...) { char str[RAYDIUM_MAX_NAME_LEN]; va_list argptr; va_start(argptr,format); vsprintf(str,format,argptr); va_end(argptr); printf("Raydium: %s\n",str); if(raydium_log_file) fprintf(raydium_log_file,"%s\n",str); raydium_console_line_add(str); } Stesso discorso per raydium_console_line_add: From raydium/console.c: // need to secure this one too void raydium_console_line_add(char *format, ...) { char str[RAYDIUM_MAX_NAME_LEN]; va_list argptr; va_start(argptr,format); vsprintf(str,format,argptr); va_end(argptr); raydium_console_line_last++; if(raydium_console_line_last>=RAYDIUM_CONSOLE_MAX_LINES) raydium_console_line_last=0; strcpy(raydium_console_lines[raydium_console_line_last],str); } ------------------------------- B] format string in raydium_log ------------------------------- La stessa funzione raydium_log descritta qui sopra e' vulnerabile anche ad un bug di tipo format string causato dalla chiamata di raydium_console_line_add con il passaggio diretto del buffer senza la stringa di formattazione necessaria: raydium_console_line_add(str); -------------------------------------------------------- C] NULL function pointer in raydium_network_netcall_exec -------------------------------------------------------- La funzione raydium_network_netcall_exec viene chiamata da raydium_network_read per selezionare la funzione specifica da usare per gestire il tipo di pacchetto ricevuto. L'array raydium_network_netcall_type e' inizializzato con il tipo -1 quindi se l'attacker usa il tipo 0xff la funzione cerchera' di chiamare raydium_network_netcall_func che pero' e' ancora inizializzato con un puntatore NULL. L'effetto e' il crash del programma. Da raydium/network.c: ... for(i=0;i