10 agosto 2009

Cinturón de seguridad, ABS y ESP para tu código fuente

Programar se asemeja mucho a conducir, se requiere tiempo para adquirir destreza, importa tener talento natural y nadie está libre de cometer errores.

Una pequeña distracción se puede convertir en un error fatal que deje un bug explotable en tu código fuente.

Indudablemente programar con una metodología segura ayuda a evitar problemas mayores, no obstante, siempre viene bien contar con una serie de ayudas extra para minimizar fallos.

En C y C++ los principales problemas que se pueden tener son los temidos buffer overflows. Con el paso del tiempo los compiladores han ido introduciendo sistemas para detectar y abortar este tipo de ataques. Veamos como activar esas protecciones en Windows y Linux:

Visual Studio

El entorno de desarrollo de Microsoft dispone desde hace tiempo de una opción que activa una protección de tipo 'Canary' para evitar que se pueda sacar partido de un overflow. Para activar esta protección, en las propiedades de nuestro proyecto:


Debemos ir a 'Generación de código' y una vez ahí seleccionar 'Comprobación de seguridad de buffer'


Linux (gcc)

En el caso de GCC tenemos disponible, mediante linea de comandos, la opción -fstack-protector-all que activa todas las protecciones de ProPolice para evitar desbordamientos de buffer.

Veamos un ejemplo real:

Tomando un binario vulnerable a un típico buffer overflow, si lo compilamos de forma normal y tratamos de explotarlo:
# gcc vulnerable.c -o vulnerable

# ./vulnerable `perl -e 'print "A"x173, "\x90"x271,"\x29\xc9\x83\xe9\xf5\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xb9\x1c\xc9\x53\x83\xeb\xfc\xe2\xf4\xd3\x17\x91\xca\xeb\x7a\xa1\x7e\xda\x95\x2e\x3b\x96\x6f\xa1\x53\xd1\x33\xab\x3a\xd7\x95\x2a\x01\x51\x14\xc9\x53\xb9\x33\xab\x3a\xd7\x33\xba\x3b\xb9\x4b\x9a\xda\x58\xd1\x49\x53","\x98\xf7\xff\xbf"'`

#
Como se puede ver, el programa es explotable y, una vez ejecutado el exploit, devuelve una shell.

Ahora con ProPolice:
# gcc -fstack-protector-all vulnerable.c -o vulnerable

# ./vulnerable `perl -e 'print "A"x173, "\x90"x271,"\x29\xc9\x83\xe9\xf5\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\xb9\x1c\xc9\x53\x83\xeb\xfc\xe2\xf4\xd3\x17\x91\xca\xeb\x7a\xa1\x7e\xda\x95\x2e\x3b\x96\x6f\xa1\x53\xd1\x33\xab\x3a\xd7\x95\x2a\x01\x51\x14\xc9\x53\xb9\x33\xab\x3a\xd7\x33\xba\x3b\xb9\x4b\x9a\xda\x58\xd1\x49\x53","\x98\xf7\xff\xbf"'`

*** stack smashing detected ***: ./vulnerable terminated
======= Backtrace: =========
/lib/libc.so.6(__fortify_fail+0x48)[0x889bd8]
/lib/libc.so.6(__fortify_fail+0x0)[0x889b90]
./vulnerable[0x804861d]
./vulnerable[0x8048700]
Abortado
ProPolice detecta y bloquea el intento haciéndolo fútil.

Lenguajes Dinámicos

En el caso de los lenguajes dinámicos los problemas son diferentes, en concreto la mayor preocupación viene a la hora de emplearlos para construir aplicaciones web. Ataques de tipo SQL Injection, XSS y derivados son un quebradero de cabeza a la hora de afrontar un desarrollo web.

En el caso de PHP existe un proyecto llamado PHP-IDS que, a modo de librería que se añade al código fuente, permite fortificar un script programado en PHP para evitar ataques.

Si tu eres de los que prefieren los Simpson a Padre de Familia y desarrollas en Perl, también existe un port de PHP-IDS llamado Perl-IDS que permite defender los scripts en Perl.

También existe un port de PHP-IDS para .NET llamado DotNetIDS

5 comments :

jg dijo...

En cuanto a Visual Studio, añadir que hay dos tipos de protecciones incluidas. Primero estan las que buscan que un overflow no sea posible, llamemoslas medidas proactivas, aqui se distinguen dos opciones de compilación o flags. Por un lado esta el flag /GS, que creo que es el que comentas en el post, que añade un valor a modo de cookie en la pila y además reorganiza las variables en la pila para que datos de la aplicación y/o argumentos no sean machacables. Por otro lado tenemos el flag /NXCOMPAT que permite que el binario compilado soporte DEP que a su vez establece regiones de memoria donde hay datos (pila, etc...) como no ejecutables.

Y para terminar estan las medidas reactivas que buscan hacer la explotación de un posible bug más dificil una vez este exista. Para ello Visual Studio incorpora el flag /DYNAMICBASE que permite al binario ser compatible con la tecnologia ASLR de las ultimas versiones de vista que recoloca el binario en memoria en momento de cargarlo para que las direcciones de datos conocidos no sean predecibles.

Un saludo!

Zerial dijo...

Está muy bueno el tip de agregar el parámetro "-fstack-protector-all" al compilador. Me pregunto si ese parámetro sirve para cualquier programa? Digo, si me bajo el codigo fuente de, por ejemplo, mplayer y lo compilo pasandole ese parametro, deberia despreocuparme por los futuros BoF que se anuncien?

saludos

Yago Jesus dijo...

@jg Excelente explicación y magnífica web.

@Zerial, si defines la variable CFLAGS (export CFLAGS = -fstack-protector-all ) debería compilar todo con ProPolice

jg dijo...

@yago Muchas gracias :)

En cuanto a lo que comentais, compilar pienso que se puede compilar con esos flags, otra cosa es que luego el programa funcione correctamente. Algunas aplicaciones no están pensadas para este tipo de medidas y es muy común (tanto en unix como en windows) que al compilarlas así den fallos y/o casquen. Esto se debe a que la mayoría de los desarrolladores no tienen tiempo/conocimiento para preocuparse por cada detalle a bajo nivel de la implementación (Existen casos en los que los bugs solo son visibles en el binario y inexistentes en el codigo fuente).

Aparte de eso, en el supuesto caso de que consigas compilar y que no casque, las medidas ProPolice no son efectivas en todos los casos. Segun como sea el bug, existe la posibilidad de alterar variables del programa que posteriormente permitan la explotación.

Resulta algo frustrante :(, pero es el eterno juego del gato y el ratón. Como bien se sabe un sistema nunca es 100% seguro y lo mejor que podrias hacer sería intentar minimizar la posible superficie de ataque, etc...pero que te voy a decir yo que google no sepa :-)

Un saludo

mac dijo...

Simpson a Padre de Familia y desarrollas en Perl,..... jajajajajaja eres un perro.