Seguramente uno de los errores más comunes, y sin duda el más conocido y
utilizado es el stack smashing o desbordamiento de pila, también
conocido por buffer overflow6.2; aunque el gusano
de Robert T. Morris (1988) ya lo utilizaba, no fué hasta 1997 cuando este
fallo se hizo realmente popular a raíz de [One96]. A pesar de que
alguien pueda pensar que en todo el tiempo trascurrido hasta hoy en día
los problemas de buffer overflow estarán solucionados, o al menos
controlados, aún se ven con frecuencia alertas sobre programas que se
ven afectados por desbordamientos (justamente hoy, 28 de febrero del 2000, han
llegado a la lista BUGTRAQ un par de
programas que aprovechaban estos errores para aumentar el nivel de privilegio
de un usuario en el sistema). Aunque cada vez los programas son más seguros,
especialmente los setuidados, es casi seguro que un potencial atacante que
acceda a nuestro sistema va a intentar - si no lo ha hecho ya - conseguir
privilegios de administrador a través de un buffer overflow.
La idea del stack smashing es sencilla: en algunas implementaciones de
C es posible corromper la pila de ejecución de un programa escribiendo
más allá de los límites de un array declarado auto en una
función; esto puede causar que la dirección de retorno de dicha función
sea una dirección aleatoria. Esto, unido a permisos de los ficheros
ejecutables en Unix (principalmente a los bits de SetUID y SetGID), hace que
el sistema operativo pueda otorgar acceso root a usuarios sin
privilegios. Por ejemplo, imaginemos una función que trate de copiar con
strcpy() un array de 200 caracteres en uno de 20: al ejecutar el programa,
se generará una violación de segmento (y por tanto el clásico core dump al que los usuarios de Unix estamos acostumbrados). Se ha producido
una sobreescritura de la dirección de retorno de la función; si logramos
que esta sobreescritura no sea aleatoria sino que apunte a un código
concreto (habitualmente el código de un shell), dicho código se va a
ejecutar.
>Cuál es el problema? El problema reside en los ficheros setuidados y
setgidados; recordemos que cuando alguien los ejecuta, está trabajando
con los privilegios de quien los creó, y todo lo que ejecute lo hace con esos
privilegios...incluido el código que se ha insertado en la dirección de
retorno de nuestra función problemática. Si como hemos dicho, este código
es el de un intérprete de comandos y el fichero pertenece al administrador,
el atacante consigue ejecutar un shell con privilegios de root.
Existen multitud de exploits (programas que aprovechan un error en otro
programa para violar la política de seguridad del sistema) disponibles
en Internet, para casi todas las variantes de Unix y que incluyen el código
necesario para ejecutar shells sobre cualquier operativo y arquitectura.
Para minimizar el impacto que los desbordamientos pueden causar en nuestro
sistema es necesaria una colaboración entre fabricantes, administradores y
programadores ([Ins97], [Smi97]...). Los primeros han de
tratar de verificar más la robustez de los programas críticos antes de
distribuirlos, mientras que los administradores han de mantener al mínimo
el número de ficheros setuidados o setgidados en sus sistemas y
los programadores tienen que esforzarse en generar código con menos puntos
de desbordamiento; en [CWP$^+$00] se pueden encontrar algunas líneas
a tener en cuenta en la prevención de buffer overflows.
© 2002 Antonio Villalón Huerta