Home Hacking y Seguridad Buffer Overflows Deshabilitando protecciones contra Buffer Overflows

Ultimos Mensajes del Foro

Manual Aleatorio

control de accesos (PDF)
Documento pdf de 42 paginas sobre todo tipo de control de accesos y sus formas de ataque.
Leer más...

Webs Amigas

Deshabilitando protecciones contra Buffer Overflows Imprimir E-mail
Hacking y Seguridad - Buffer Overflows
Escrito por c1c4tr1z   
Cuando es el momento de analizar un programa en busca de vulnerabilidades o simplemente explotarlos bajo GNU/Linux, hay dos simples protecciones que hay que tener en cuanta cuando hablamos de sistemas con Kernels de versiones 2.6 y mayores, y por sobre todo si están compilados con GCC. Hay mas protecciones como el parche grsecurity o exec-shield (de los que quizás hable mas adelante), hasta existe una protección desde hardware llamado StackGuard.



Texto Completo:

Deshabilitando protecciones contra Buffer Overflows

-------------------------------------------------------------------------------
Cuando es el momento de analizar un programa en busca de vulnerabilidades o
simplemente explotarlos bajo GNU/Linux, hay dos simples protecciones que hay
que tener en cuanta cuando hablamos  de sistemas con Kernels de versiones 2.6 y
mayores, y por sobre todo si estn compilados con GCC. Hay mas protecciones
como el parche grsecurity o exec-shield (de los que quizs hable mas adelante),
hasta existe una proteccin desde hardware llamado StackGuard.

Virtual Address Space Randomization:

La primera proteccin es la creacin de espacio  de direcciones virtuales
aleatorias en el proceso, que van cambiando con cada invocacin del proceso. Al
cambiar esto, los exploits creados para direcciones absolutas (osea,
constantes) serian obsoletos ya que cambian las direcciones con cada ejecucin
del programa y sus libreras en un rango de 8MB. Esto se aplica solamente a
binarios ELF (Executable and Linkable Format).
El mtodo para habilitarlo y deshabilitarlo es simple, voy a demostrar el
cambio de direcciones en la memoria con el siguiente cdigo:

Co'digo:

#include 

unsigned long esp(void){
        __asm__("movl %esp, %eax");
}

int main(int argc, char *argv[]){
        printf("0x%08x\n",esp());
        return 0;
}


Este cdigo me dara la direccin exacta de ESP en el momento de la ejecucin.
Ahora con este cdigo vamos a probar la proteccin en si del kernel en
cuestin. El archivo de sistema que controla esta opcin se encuentra en /proc/
sys/kernel/randomize_va_space (solo manipulado por un superusuario o root) y
podramos decir que se controla mediante un TRUE (1) o FALSE (0). Entonces,
probemos:

Co'digo:

c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat /proc/sys/kernel/randomize_va_space
1
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat > esp.c << _END_
> #include 
>
> unsigned long esp(void){
> __asm__("movl %esp, %eax");
> }
>
> int main(int argc, char *argv[]){
> printf("0x%08x\n",esp());
> return 0;
> }
>
> _END_
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gcc esp.c -o esp
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$  ./esp
0xbfef2448
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbfd48298
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbfa24778
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$


Mediante la habilitacin de este "parche" podemos ver que las direcciones van
cambiando y haciendo casi imposible saber la direccin virtual de ESP (en este
caso..) hasta el momento de la ejecucin. Ahora deshabilitemos esta funcin y
veamos que pasa:

Co'digo:

root@c1c4tr1z-desktop:~# echo 0 > /proc/sys/kernel/randomize_va_space
[...]
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat /proc/sys/kernel/randomize_va_space
0
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbffff558
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbffff558
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
0xbffff558
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$


Despus de deshabilitar el parche podemos ver que la direccin de ESP es
constante en el ejecutable, sin siquiera volver a compilarlo!
Pero no se asusten, como la historia nos ha enseado! Detras de cada sistema de
seguridad hay alguien tratando de romperlo.. [1]

GCC StackGuard (ProPolice) Protection:

Bueno, esta es una proteccion de seguridad implementada en el compilador ultra
renombrado y que se encuentra en cada distribucin GNU/Linux , hablo de GCC
(GNU Compiler Collection). Este compilador viene con un sistema de proteccin
llamado "StackGuard" desarrollado por Immunix y ahora llamado ProPolice [2].
Esta proteccin detecta un ataque de buffer overflow (siempre en el "stack")
creando un valor llamado "Canario" entre los buffers creados y el "frame
pointer" (EBP) & "return address" (EIP), entonces cuando un buffer intenta
sobreescribir estos valores tiene que de una forma o otra sobreescribir el
valor "Canario" y esto sirve como lanzador ("trigger") de la proteccion que da
una alerta y toma una accin contra ello, por ejemplo, deteniendo el proceso.
Bueno, vamos a ver como reacciona a un simple overflow como este:

Co'digo:

#include 
#include 

void overflow(char *badbeef){
        char buffer[32];
        strcpy(buffer, badbeef);
}

int main(int argc, char *argv[]){
        overflow(argv[1]);
        return 0;
}



Como vemos, hay un buffer de 32 bytes y ni un solo checkeo al hacer la copia de
string al buffer. Ya sabemos que tenemos 32 bytes de buffer + EBP +  EIP, pero
si la proteccin esta habilitada no nos permitira ni pasar de el "frame
pointer":
Co'digo:


c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat > vulnerable.c <<_END_
> #include 
> #include 
>
> void overflow(char *badbeef){
> char buffer[32];
> strcpy(buffer, badbeef);
> }
>
> int main(int argc, char *argv[]){
> overflow(argv[1]);
> return 0;
> }
>
> _END_
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gcc vulnerable.c -o vulnerable
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x32')
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x36#EBP')
*** stack smashing detected ***: ./vulnerable terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7f69138]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7f690f0]
./vulnerable[0x80483fe]
./vulnerable[0x8048421]
[0x41414141]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
08049000-0804a000 rw-p 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
b7e70000-b7e7a000 r-xp 00000000 08:02 197220     /lib/libgcc_s.so.1
b7e7a000-b7e7b000 rw-p 0000a000 08:02 197220     /lib/libgcc_s.so.1
b7e7b000-b7e7c000 rw-p b7e7b000 00:00 0
b7e7c000-b7fc5000 r-xp 00000000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc5000-b7fc6000 r--p 00149000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc6000-b7fc8000 rw-p 0014a000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc8000-b7fcb000 rw-p b7fc8000 00:00 0
b7fe1000-b7fe3000 rw-p b7fe1000 00:00 0
b7fe3000-b7fe4000 r-xp b7fe3000 00:00 0          [vdso]
b7fe4000-b7ffe000 r-xp 00000000 08:02 196676     /lib/ld-2.7.so
b7ffe000-b8000000 rw-p 00019000 08:02 196676     /lib/ld-2.7.so
bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
Cancelado
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x44#EIP')
*** stack smashing detected ***: ./vulnerable terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7f69138]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7f690f0]
./vulnerable[0x80483fe]
[0x41414141]
======= Memory map: ========
08048000-08049000 r-xp 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
08049000-0804a000 rw-p 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
b7e70000-b7e7a000 r-xp 00000000 08:02 197220     /lib/libgcc_s.so.1
b7e7a000-b7e7b000 rw-p 0000a000 08:02 197220     /lib/libgcc_s.so.1
b7e7b000-b7e7c000 rw-p b7e7b000 00:00 0
b7e7c000-b7fc5000 r-xp 00000000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc5000-b7fc6000 r--p 00149000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc6000-b7fc8000 rw-p 0014a000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
b7fc8000-b7fcb000 rw-p b7fc8000 00:00 0
b7fe1000-b7fe3000 rw-p b7fe1000 00:00 0
b7fe3000-b7fe4000 r-xp b7fe3000 00:00 0          [vdso]
b7fe4000-b7ffe000 r-xp 00000000 08:02 196676     /lib/ld-2.7.so
b7ffe000-b8000000 rw-p 00019000 08:02 196676     /lib/ld-2.7.so
bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
Cancelado


DETECTADO! Si analizamos mas de cerca vemos esto ./vulnerable[0x80483ef], esa
direccion nos indica en que momento el programa ejecuta el buffer overflow:

Co'digo:

c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gdb -q vulnerable
(gdb) disas 0x80483ef
Dump of assembler code for function overflow:
0x080483c4 :        push   %ebp
0x080483c5 :        mov    %esp,%ebp
0x080483c7 :        sub    {jumi [*3] [http://www.govannom.org/seguridad/buf_overf/evit_prot_buf_overf.txt]}x48,%esp
0x080483ca :        mov    0x8(%ebp),%eax
0x080483cd :        mov    %eax,-0x34(%ebp)
0x080483d0 :       mov    %gs:0x14,%eax
0x080483d6 :       mov    %eax,-0x4(%ebp)
0x080483d9 :       xor    %eax,%eax
0x080483db :       mov    -0x34(%ebp),%eax
0x080483de :       mov    %eax,0x4(%esp)
0x080483e2 :       lea    -0x24(%ebp),%eax
0x080483e5 :       mov    %eax,(%esp)
[b]0x080483e8 :    call   0x8048320 [/b]
0x080483ed :       mov    -0x4(%ebp),%eax
0x080483f0 :       xor    %gs:0x14,%eax
0x080483f7 :       je     0x80483fe 
0x080483f9 :       call   0x8048330 <__stack_chk_fail@plt>
0x080483fe :       leave
0x080483ff :       ret   
End of assembler dump.


Como vemos detiene el programa en la instrucci leave, que (por lo que
entiendo) es la encargada de mover (mov) a %ebp a %esp y sacar (pop) a %ebp de
la pila, eso significaria que pretende volver a ESP y con el buffer copiado (
call   0x8048320 ). Es ahi donde el canario es sobreescrito y se
detiene todo el procedimiento despues del checkeo. El checkeo lo hace mediante
la funcion __stack_chk_fail().
Ahora vamos a probar el programa _sin_ esta proteccin. Para eso vamos a
compilar el programa con el flag --no-stack-protector:

Co'digo:

c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gcc --no-stack-protector vulnerable.c -o vulnerable
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x44#EIP')
Fallo de segmentacin
c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gdb -q vulnerable
(gdb) r $(perl -e 'print "A"x36 ,"B"x4')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home/c1c4tr1z/Escritorio/vulnerable $(perl -e 'print "A"x36 ,"B"x4')

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) i r eip ebp
eip            0x42424242       0x42424242
ebp            0x41414141       0x41414141
(gdb)


Y sin esta proteccin pudimos sobreescribir EBP y EIP sin ninguna dificultad,
cosa que seria fcil de explotar mas an si la proteccin de la cual hable
antes esta deshabilitada para poder conseguir la direccin constante de ESP y
sobreescribir el flujo del proceso. En s, yo solo hable de un solo mtodo de
proteccin de esta extensin, que por lo que s son 5 y se pueden ver en al
pagina oficial [2].

Espero que les haya gustado esta pequea charla, si tienen  alguna pregunta o
recalcarme en algo que estuve mal por favor haganlo ya que me estaran ayudando
a mi y a los lectores :D porque apenas entro en el mundo de los exploits a
nivel de sistema y la *lectura* de cdigos en ASM.

       << en: 14 Enero 2009, 01:28 >>

Referencias:
[1] Smack the Stack (Advanced Buffer Overflow Methods) - http://
www.packetstormsecurity.org/papers/bypass/smackthestack.txt
[2] ProPolice - http://www.trl.ibm.com/projects/security/ssp/