comment
IRC Chat
play_arrow
Este sitio utiliza cookies propias y de terceros. Si continúa navegando consideramos que acepta el uso de cookies. OK Más Información.

Deshabilitando protecciones contra Buffer Overflows

  • 0 Respuestas
  • 1690 Vistas

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado LucaSthefano

  • *
  • Underc0der
  • Mensajes: 399
  • Actividad:
    0%
  • Reputación 0
    • Ver Perfil
« en: Julio 19, 2011, 03:58:20 pm »
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 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.


Virtual Address Space Randomization

La primera protección es la creación de espacio  de direcciones virtuales aleatorias en el proceso, que van cambiando con cada invocación del proceso. Al cambiar esto, los exploits creados para direcciones absolutas (osea, constantes) serian obsoletos ya que cambian las direcciones con cada ejecución del programa y sus librerías en un rango de 8MB. Esto se aplica solamente a binarios ELF (Executable and Linkable Format).

El método para habilitarlo y deshabilitarlo es simple, voy a demostrar el cambio de direcciones en la memoria con el siguiente código:

Código: C++
  1. #include <stdio.h>
  2.  
  3. unsigned long esp(void){
  4.         __asm__("movl %esp, %eax");
  5. }
  6.  
  7. int main(int argc, char *argv[]){
  8.         printf("0x%08x\n",esp());
  9.         return 0;
  10. }
  11.  

Este código me daría la dirección exacta de ESP en el momento de la ejecución. Ahora con este código vamos a probar la protección en si del kernel en cuestión. El archivo de sistema que controla esta opción se encuentra en /proc/sys/kernel/randomize_va_space (solo manipulado por un superusuario o root) y podríamos decir que se controla mediante un TRUE (1) o FALSE (0). Entonces, probemos:

Código: Text
  1. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat /proc/sys/kernel/randomize_va_space
  2. 1
  3. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat > esp.c << _END_
  4. > #include <stdio.h>
  5. >
  6. > unsigned long esp(void){
  7. > __asm__("movl %esp, %eax");
  8. > }
  9. >
  10. > int main(int argc, char *argv[]){
  11. > printf("0x%08x\n",esp());
  12. > return 0;
  13. > }
  14. >
  15. > _END_
  16. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gcc esp.c -o esp
  17. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$  ./esp
  18. 0xbfef2448
  19. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
  20. 0xbfd48298
  21. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
  22. 0xbfa24778
  23. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$
  24.  

Mediante la habilitación de este "parche" podemos ver que las direcciones van cambiando y haciendo casi imposible saber la dirección virtual de ESP (en este caso..) hasta el momento de la ejecución. Ahora deshabilitemos esta función y veamos que pasa:

Código: Text
  1. root@c1c4tr1z-desktop:~# echo 0 > /proc/sys/kernel/randomize_va_space
  2. [...]
  3. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat /proc/sys/kernel/randomize_va_space
  4. 0
  5. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
  6. 0xbffff558
  7. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
  8. 0xbffff558
  9. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./esp
  10. 0xbffff558
  11. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$
  12.  

Después de deshabilitar el parche podemos ver que la dirección de ESP es constante en el ejecutable, sin siquiera volver a compilarlo!
Pero no se asusten, como la historia nos ha enseñado! 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 distribución GNU/Linux , hablo de GCC (GNU Compiler Collection). Este compilador viene con un sistema de protección llamado "StackGuard" desarrollado por Immunix y ahora llamado ProPolice [2]. Esta protección 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 acción contra ello, por ejemplo, deteniendo el proceso.
Bueno, vamos a ver como reacciona a un simple overflow como este:

Código: C++
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. void overflow(char *badbeef){
  5.         char buffer[32];
  6.         strcpy(buffer, badbeef);
  7. }
  8.  
  9. int main(int argc, char *argv[]){
  10.         overflow(argv[1]);
  11.         return 0;
  12. }
  13.  
  14.  

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 protección esta habilitada no nos permitiría ni pasar de el "frame pointer":


Código: Text
  1. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ cat > vulnerable.c <<_END_
  2. > #include <stdio.h>
  3. > #include <string.h>
  4. >
  5. > void overflow(char *badbeef){
  6. > char buffer[32];
  7. > strcpy(buffer, badbeef);
  8. > }
  9. >
  10. > int main(int argc, char *argv[]){
  11. > overflow(argv[1]);
  12. > return 0;
  13. > }
  14. >
  15. > _END_
  16. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gcc vulnerable.c -o vulnerable
  17. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x32')
  18. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x36#EBP')
  19. *** stack smashing detected ***: ./vulnerable terminated
  20. ======= Backtrace: =========
  21. /lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7f69138]
  22. /lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7f690f0]
  23. ./vulnerable[0x80483fe]
  24. ./vulnerable[0x8048421]
  25. [0x41414141]
  26. ======= Memory map: ========
  27. 08048000-08049000 r-xp 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
  28. 08049000-0804a000 rw-p 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
  29. 0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
  30. b7e70000-b7e7a000 r-xp 00000000 08:02 197220     /lib/libgcc_s.so.1
  31. b7e7a000-b7e7b000 rw-p 0000a000 08:02 197220     /lib/libgcc_s.so.1
  32. b7e7b000-b7e7c000 rw-p b7e7b000 00:00 0
  33. b7e7c000-b7fc5000 r-xp 00000000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
  34. b7fc5000-b7fc6000 r--p 00149000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
  35. b7fc6000-b7fc8000 rw-p 0014a000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
  36. b7fc8000-b7fcb000 rw-p b7fc8000 00:00 0
  37. b7fe1000-b7fe3000 rw-p b7fe1000 00:00 0
  38. b7fe3000-b7fe4000 r-xp b7fe3000 00:00 0          [vdso]
  39. b7fe4000-b7ffe000 r-xp 00000000 08:02 196676     /lib/ld-2.7.so
  40. b7ffe000-b8000000 rw-p 00019000 08:02 196676     /lib/ld-2.7.so
  41. bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
  42. Cancelado
  43. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x44#EIP')
  44. *** stack smashing detected ***: ./vulnerable terminated
  45. ======= Backtrace: =========
  46. /lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xb7f69138]
  47. /lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xb7f690f0]
  48. ./vulnerable[0x80483fe]
  49. [0x41414141]
  50. ======= Memory map: ========
  51. 08048000-08049000 r-xp 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
  52. 08049000-0804a000 rw-p 00000000 08:02 534536     /home/c1c4tr1z/Escritorio/vulnerable
  53. 0804a000-0806b000 rw-p 0804a000 00:00 0          [heap]
  54. b7e70000-b7e7a000 r-xp 00000000 08:02 197220     /lib/libgcc_s.so.1
  55. b7e7a000-b7e7b000 rw-p 0000a000 08:02 197220     /lib/libgcc_s.so.1
  56. b7e7b000-b7e7c000 rw-p b7e7b000 00:00 0
  57. b7e7c000-b7fc5000 r-xp 00000000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
  58. b7fc5000-b7fc6000 r--p 00149000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
  59. b7fc6000-b7fc8000 rw-p 0014a000 08:02 1425929    /lib/tls/i686/cmov/libc-2.7.so
  60. b7fc8000-b7fcb000 rw-p b7fc8000 00:00 0
  61. b7fe1000-b7fe3000 rw-p b7fe1000 00:00 0
  62. b7fe3000-b7fe4000 r-xp b7fe3000 00:00 0          [vdso]
  63. b7fe4000-b7ffe000 r-xp 00000000 08:02 196676     /lib/ld-2.7.so
  64. b7ffe000-b8000000 rw-p 00019000 08:02 196676     /lib/ld-2.7.so
  65. bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
  66. Cancelado
  67.  

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

Código: Text
  1. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gdb -q vulnerable
  2. (gdb) disas 0x80483ef
  3. Dump of assembler code for function overflow:
  4. 0x080483c4 <overflow+0>:        push   %ebp
  5. 0x080483c5 <overflow+1>:        mov    %esp,%ebp
  6. 0x080483c7 <overflow+3>:        sub    $0x48,%esp
  7. 0x080483ca <overflow+6>:        mov    0x8(%ebp),%eax
  8. 0x080483cd <overflow+9>:        mov    %eax,-0x34(%ebp)
  9. 0x080483d0 <overflow+12>:       mov    %gs:0x14,%eax
  10. 0x080483d6 <overflow+18>:       mov    %eax,-0x4(%ebp)
  11. 0x080483d9 <overflow+21>:       xor    %eax,%eax
  12. 0x080483db <overflow+23>:       mov    -0x34(%ebp),%eax
  13. 0x080483de <overflow+26>:       mov    %eax,0x4(%esp)
  14. 0x080483e2 <overflow+30>:       lea    -0x24(%ebp),%eax
  15. 0x080483e5 <overflow+33>:       mov    %eax,(%esp)
  16. [b]0x080483e8 <overflow+36>:    call   0x8048320 <strcpy@plt>[/b]
  17. 0x080483ed <overflow+41>:       mov    -0x4(%ebp),%eax
  18. 0x080483f0 <overflow+44>:       xor    %gs:0x14,%eax
  19. 0x080483f7 <overflow+51>:       je     0x80483fe <overflow+58>
  20. 0x080483f9 <overflow+53>:       call   0x8048330 <__stack_chk_fail@plt>
  21. 0x080483fe <overflow+58>:       leave
  22. 0x080483ff <overflow+59>:       ret    
  23. End of assembler dump.
  24.  

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 <strcpy@plt>). 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 protección. Para eso vamos a compilar el programa con el flag --no-stack-protector:

Código: Text
  1. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gcc --no-stack-protector vulnerable.c -o vulnerable
  2. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ ./vulnerable $(perl -e 'print "A"x44#EIP')
  3. Fallo de segmentación
  4. c1c4tr1z@c1c4tr1z-desktop:~/Escritorio$ gdb -q vulnerable
  5. (gdb) r $(perl -e 'print "A"x36 ,"B"x4')
  6. The program being debugged has been started already.
  7. Start it from the beginning? (y or n) y
  8.  
  9. Starting program: /home/c1c4tr1z/Escritorio/vulnerable $(perl -e 'print "A"x36 ,"B"x4')
  10.  
  11. Program received signal SIGSEGV, Segmentation fault.
  12. 0x42424242 in ?? ()
  13. (gdb) i r eip ebp
  14. eip            0x42424242       0x42424242
  15. ebp            0x41414141       0x41414141
  16. (gdb)
  17.  

Y sin esta protección pudimos sobreescribir EBP y EIP sin ninguna dificultad, cosa que seria fácil de explotar mas aún si la protección de la cual hable antes esta deshabilitada para poder conseguir la dirección constante de ESP y sobreescribir el flujo del proceso. En sí, yo solo hable de un solo método de protección de esta extensión, que por lo que sé son 5 y se pueden ver en al pagina oficial [2].

Referencias:
[1] Smack the Stack (Advanced Buffer Overflow Methods) - You are not allowed to view links. Register or Login
[2] ProPolice - You are not allowed to view links. Register or Login

Autor: c1c4tr1z
« Última modificación: Noviembre 23, 2014, 02:45:03 pm por Expermicid »

 

¿Te gustó el post? COMPARTILO!