Ayer hablando con un conocido en el IRC me comentó que había un exploit en milw0rm en él que en realidad la shellcode ejecutaba un “rm -rf /”.
Se trataba de este exploit:
http://raise.enye-sec.org/archivos/lul-busybox.c
(actualizado: lo he subido a mi servidor porque ya lo habían borrado de milw0rm)
En teoría explota un bug de formato del busybox, que es una especie de conjunto de utilidades de consola orientado a sistemas empotrados. El tema es que en la versión de uname (unix name) del busybox hay un bug de formato, concretamente:
linea 92 de coreutils/uname.c:
printf(((char *)(&uname_info)) + *delta);
Como vemos en realidad si que existe un bug de formato, el problema es que el ‘exploit’ simula explotar esta vulnerabilidad, pero en realidad no lo hace. Para empezar la shellcode que lleva ejecuta un execve(”/bin//rm”, “-f”, “-r”, NULL), cuando en el exploit dice que ejecuta una shell. Luego además en los comentarios del exploit aparece el supuesto codigo en ensamblador de la shellcode, que es falso:
/*
“\x6a\x0b” // push $0xb
“\x58″ // pop %eax
“\x99″ // cltd
“\x52″ // push %edx
“\x68\x2f\x2f\x73\x68″ // push $0×68732f2f
“\x68\x2f\x62\x69\x6e” // push $0×6e69622f
“\x89\xe3″ // mov %esp, %ebx
“\x52″ // push %edx
“\x53″ // push %ebx
“\x89\xe1″ // mov %esp, %ecx
“\xcd\x80″; // int $0×80
*/
Esos comentarios están muy chulos, pero el código real de la shellcode es otro muy diferente. Luego para colmo el exploit lleva mucho código ofuscado, con lo que es dificil saber que hace exactamente. Para empezar en los comentarios dice que hay que compilarlo como una librería, y ejecutar:
export LD_PRELOAD=”./busybox.so”
Con esto conseguimos que se carge esa libreria dinámica antes que la propia libc. El busybox (y el propio binario de /bin/uname también) lo que hace es llamar a la función uname() de la libc. Pero claro, al cargar esa libreria primero llama a la función uname() de busybox.so, con lo que el control de la CPU ya está tomado (hay que decir que si un binario tiene setuid el sistema ignora la variable LD_PRELOAD). Aquí el exploit podría ejecutar directamente lo que quisera, pero claro, hay que hacer un poco el paripé para intentar despistar al personal.
Por lo que he investigado (poco), según mi parecer lo que hace (o intenta mejor dicho, porque el código está bastante chapuzado) es tratar de sobreescribir la dirección de retorno de la función uname_main() del busybox. ¿Como?, pues a través de un puntero que apunta a una variable local (usease en la pila) dentro de dicha función. Concretamente el puntero es el argumento que recibe la función uname() del exploit: struct utsname *buf. Esa estructura (finita, en realidad ocupa unos 200 y pico bytes así a ojo) es declarada dentro de la funcion uname_main(), con lo que si sobreescribimos muchos bytes llegaremos a la dirección de retorno.
Y eso es lo que hace el exploit a traves de una llamada a build_fmt(), se dedica a hacer chorradas para despistar, y al final copia mediante un bucle lo que parece ser una dirección hardcodeada de donde debería estar la shellcode (incrementando la dirección +2 en cada iteración, lo cual no tiene mucho sentido). Según mi criterio dudo que ese código llegue a funcionar alguna vez, pero bueno… Ah, también copia una especie de string de formato para ‘explotar’ el bug:
p += sprintf(p, “%%%d$%uu%%%d$hn”
Ya me contarás como explotas un bug de formato sin un %n …, todo eso solo es para dar intentar dar más el pego.
Resumiendo, que pedazo de fake, y encima está en milw0rm, packetstorm, y en todas partes… He enviado un par de mails, el de milw0rm ya me ha contestado y seguramente quite el exploit. Encima en milw0rm hay otro exploit superofuscado del susodicho elemento, solo hay que verlo (ya me contareis que narices hace eso X-D). Y también tienen página web: lul-disclosure.net. Les iba a mandar un mail, pero con los problemas que tuve ultimamente con los DDoS casi que pasando, no vaya a ser que les de por ahí.
Pues nada, que mucho cuidado con lo que ejecutais.
Un saludo.