Bash Scripting para Hacking Ético: Guía Práctica con Scripts Reales

> Disclaimer legal: Todo lo que describes aquí debe practicarse exclusivamente en entornos autorizados: máquinas propias, laboratorios virtuales, plataformas como HackTheBox o TryHackMe, o sistemas donde tengas permiso explícito por escrito. Usar estas técnicas contra sistemas sin autorización es ilegal en prácticamente todos los países.


Tabla de contenidos

  1. Qué vas a aprender
  2. Por qué Bash y no Python para empezar
  3. Fundamentos de Bash scripting para hacking ético
  4. Tu primer script de reconocimiento real
  5. El error que me costó una hora
  6. Automatización de tareas repetitivas en pentesting
  7. Manejo de outputs y generación de reportes
  8. Errores comunes y cómo evitarlos
  9. Próximos pasos
  10. FAQ

Qué vas a aprender (y qué necesitas antes de empezar)

La automatización en shell scripting para hacking ético es una de las habilidades más prácticas que puedes desarrollar si ya tienes experiencia básica en pentesting. Si llevas tiempo en ciberseguridad y todavía escribes los mismos comandos a mano cada vez que arrancas una sesión, este artículo es para ti. No voy a enseñarte Bash desde cero como si fuera un curso universitario. Voy a mostrarte cómo usar scripts para automatizar las tareas repetitivas que aparecen en cada engagement: reconocimiento, escaneo de puertos, validación de servicios, generación de reportes básicos.

Antes de continuar necesitas:

  • Saber moverte por una terminal Linux (cd, ls, cat, grep — lo básico)
  • Tener acceso a una máquina Linux, ya sea nativa, una VM con Kali/Parrot, o WSL2
  • Haber ejecutado nmap al menos una vez aunque sea sin entender todos los flags

Si cumples eso, sigues. Si no, instala Kali en VirtualBox esta tarde y vuelve.

El tiempo real para completar todo lo de este artículo y tener tus primeros scripts de bash para hacking funcionando: entre 3 y 5 horas, dependiendo de cuánto experimentes.


Por qué Bash y no Python para empezar con hacking ético

Esta pregunta me la hacen constantemente cuando hablo de automatización de pentesting con shell scripting. La respuesta corta: porque Bash ya está ahí.

En cualquier sistema Linux comprometido, en cualquier shell reversa que obtengas, en cualquier contenedor mal configurado — Bash está disponible. Python no siempre. No necesitas instalar nada, no hay dependencias que resolver, no hay entornos virtuales que activar.

La observación técnica que la mayoría de tutoriales omite: Bash no es más lento que Python para scripts de reconocimiento en red. Cuando el cuello de botella es la latencia de red (que es casi siempre), el lenguaje del script es irrelevante. He comparado un scanner de puertos en Bash contra uno equivalente en Python puro y la diferencia es de milisegundos cuando haces 254 hosts en una /24. Lo que importa es el paralelismo, no el lenguaje.

Además, entender Bash te hace mejor con Python después, no al revés.


Fundamentos de Bash scripting para hacking ético que realmente usarás

Olvida los tutoriales que te enseñan a hacer calculadoras con Bash. Esto es lo que usas en campo cuando aplicas automatización en shell scripting para pentesting real.

Variables y argumentos

bash

#!/bin/bash

TARGET=$1

PORTS=$2

if [ -z «$TARGET» ]; then

echo «Uso: $0 «

echo «Ejemplo: $0 192.168.1.1 22,80,443»

exit 1

fi

echo «[*] Objetivo: $TARGET»

echo «[*] Puertos: $PORTS»

$1 y $2 son los argumentos que pasas al ejecutar el script. $0 es el nombre del script mismo. Esto es lo primero que pones en cualquier herramienta de pentesting: validación de input. Si no lo haces, el script falla de formas poco elegantes y tardas más en debuggear.

Bucles que importan en pentesting

bash

#!/bin/bash

Iterar sobre un rango de IPs en una subred /24

SUBNET=»192.168.1″

for i in $(seq 1 254); do

ping -c 1 -W 1 «$SUBNET.$i» &> /dev/null && echo «[+] Host activo: $SUBNET.$i»

done

Este loop básico es el núcleo de cualquier host discovery manual. El -W 1 limita el timeout a 1 segundo por host. Sin eso, en una red con muchos hosts caídos, el script tarda horas.

Condicionales con outputs de comandos

bash

#!/bin/bash

HOST=$1

if nmap -p 22 –open -T4 «$HOST» 2>/dev/null | grep -q «22/tcp open»; then

echo «[+] SSH abierto en $HOST»

else

echo «[-] SSH cerrado o filtrado»

fi

La parte 2>/dev/null redirige los errores al vacío. Importante cuando corres scripts de seguridad ofensiva en entornos donde nmap puede generar warnings que ensucian el output.


Tu primer script de reconocimiento real con Bash

Este es el script con el que empecé a automatizar mis sesiones en HackTheBox aplicando automatización de reconocimiento en shell. No es perfecto, pero funciona y puedes entender cada línea.

bash

#!/bin/bash

recon.sh – Script básico de reconocimiento

Uso: ./recon.sh

Solo usar en entornos autorizados

TARGET=$1

OUTPUTDIR=»recon$TARGET»

if [ -z «$TARGET» ]; then

echo «[-] Especifica un objetivo: $0 «

exit 1

fi

mkdir -p «$OUTPUT_DIR»

echo «[*] Iniciando reconocimiento en $TARGET»

echo «[*] Resultados en: $OUTPUT_DIR/»

Fase 1: Host discovery

echo «[*] Verificando si el host responde…»

if ! ping -c 2 -W 2 «$TARGET» &> /dev/null; then

echo «[!] El host no responde a ping (puede estar filtrado, continúa de todas formas)»

fi

Fase 2: Escaneo rápido de puertos

echo «[*] Escaneo rápido de puertos…»

nmap -T4 -p- –min-rate 5000 «$TARGET» -oN «$OUTPUTDIR/puertosrapido.txt» 2>/dev/null

Extraer puertos abiertos

PUERTOS=$(grep «^[0-9]» «$OUTPUTDIR/puertosrapido.txt» | grep «open» | cut -d’/’ -f1 | tr ‘\n’ ‘,’ | sed ‘s/,$//’)

if [ -z «$PUERTOS» ]; then

echo «[-] No se encontraron puertos abiertos»

exit 0

fi

echo «[+] Puertos abiertos: $PUERTOS»

Fase 3: Escaneo detallado en puertos encontrados

echo «[*] Escaneo detallado de servicios…»

nmap -sC -sV -p «$PUERTOS» «$TARGET» -oN «$OUTPUT_DIR/servicios.txt» 2>/dev/null

echo «[+] Reconocimiento completado. Revisa $OUTPUT_DIR/»

Cuando ejecutas este script de bash para hacking ético contra una máquina de práctica, el output en terminal se ve así:

[*] Iniciando reconocimiento en 10.10.11.42

[*] Resultados en: recon_10.10.11.42/

[*] Verificando si el host responde…

[*] Escaneo rápido de puertos…

[+] Puertos abiertos: 22,80,8080

[*] Escaneo detallado de servicios…

[+] Reconocimiento completado. Revisa recon_10.10.11.42/

Y dentro de recon_10.10.11.42/servicios.txt encuentras algo como:

PORT STATE SERVICE VERSION

22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5

80/tcp open http Apache httpd 2.4.41

8080/tcp open http Apache Tomcat 9.0.65


El error que me costó una hora (y cómo evitarlo)

La primera vez que usé este script de reconocimiento en una máquina de HTB con muchos puertos abiertos, el comando para extraer los puertos falló silenciosamente. El script continuaba pero $PUERTOS estaba vacío, así que el escaneo detallado no hacía nada.

El problema estaba en esta línea:

bash

PUERTOS=$(grep «^[0-9]» «$OUTPUTDIR/puertosrapido.txt» | grep «open» | cut -d’/’ -f1 | tr ‘\n’ ‘,’ | sed ‘s/,$//’)

El archivo de nmap con el flag -oN tiene un formato específico. Cuando el escaneo es muy rápido (--min-rate 5000), a veces nmap no termina de escribir el archivo antes de que el script intente leerlo. La solución fue agregar un pequeño sleep y verificar que el archivo tenga contenido:

bash

sleep 2

if [ ! -s «$OUTPUTDIR/puertosrapido.txt» ]; then

echo «[-] El archivo de resultados está vacío. Verifica permisos o conectividad.»

exit 1

fi

Advertencia real que la mayoría de tutoriales de automatización de pentesting omite: –min-rate 5000 puede generar falsos negativos en redes con pérdida de paquetes o hosts con rate limiting. En entornos de CTF es perfecto. En un pentest real contra infraestructura de producción, baja esa tasa o directamente quítala y deja que nmap use su timing por defecto. He visto puertos reales no aparecer en escaneos agresivos contra firewalls que dropean conexiones rápidas.


Automatización de tareas repetitivas en pentesting con Bash

Una vez que tienes el reconocimiento automatizado, el siguiente punto de dolor es la enumeración de servicios. Siempre hago lo mismo cuando encuentro HTTP: whatweb, curl de headers, gobuster. Lo automaticé con shell scripting así:

bash

#!/bin/bash

enum_web.sh – Enumeración básica de servicios web

Uso: ./enum_web.sh

TARGET=$1

PORT=$2

URL=»http://$TARGET:$PORT»

OUTPUT=»enumweb${TARGET}_${PORT}»

mkdir -p «$OUTPUT»

echo «[*] Enumerando $URL»

Headers HTTP

echo «[*] Obteniendo headers…»

curl -sI «$URL» > «$OUTPUT/headers.txt» 2>/dev/null

cat «$OUTPUT/headers.txt»

Tecnologías detectadas

echo «[*] Detectando tecnologías…»

if command -v whatweb &> /dev/null; then

whatweb -a 3 «$URL» > «$OUTPUT/whatweb.txt» 2>/dev/null

cat «$OUTPUT/whatweb.txt»

else

echo «[!] whatweb no instalado. Instálalo con: sudo apt install whatweb»

fi

Fuzzing de directorios

echo «[*] Iniciando fuzzing de directorios…»

if command -v gobuster &> /dev/null; then

gobuster dir -u «$URL» \

-w /usr/share/wordlists/dirb/common.txt \

-o «$OUTPUT/gobuster.txt» \

-t 30 \

–no-error \

-q 2>/dev/null

echo «[+] Resultados en $OUTPUT/gobuster.txt»

else

echo «[!] gobuster no instalado. Instálalo con: sudo apt install gobuster»

fi

echo «[+] Enumeración web completada»

El command -v antes de cada herramienta es un hábito que adopté después de que un script de automatización me fallara a mitad de un CTF porque gobuster no estaba instalado en la VM nueva. Mejor verificar y avisar que fallar silenciosamente.


Manejo de outputs y generación de reportes en Bash para pentesting

El output desordenado en terminal es el enemigo de la productividad en seguridad ofensiva. Con shell scripting puedes estructurarlo desde el principio:

bash

#!/bin/bash

Colores para output legible

RED=’\033[0;31m’

GREEN=’\033[0;32m’

YELLOW=’\033[1;33m’

BLUE=’\033[0;34m’

NC=’\033[0m’ # Sin color

Funciones de logging

log_info() { echo -e «${BLUE}[*]${NC} $1»; }

log_success() { echo -e «${GREEN}[+]${NC} $1»; }

log_warning() { echo -e «${YELLOW}[!]${NC} $1»; }

log_error() { echo -e «${RED}[-]${NC} $1»; }

Función para generar reporte básico en texto

generar_reporte() {

local TARGET=$1

local OUTPUT_DIR=$2

local REPORTE=»$OUTPUTDIR/reporte$(date +%Y%m%d_%H%M%S).txt»

{

echo «============================================»

echo «REPORTE DE RECONOCIMIENTO»

echo «Objetivo: $TARGET»

echo «Fecha: $(date)»

echo «============================================»

echo «»

echo «— PUERTOS Y SERVICIOS —«

cat «$OUTPUT_DIR/servicios.txt» 2>/dev/null || echo «No disponible»

echo «»

echo «— ENUMERACIÓN WEB —«

cat «$OUTPUT_DIR/gobuster.txt» 2>/dev/null || echo «No disponible»

} > «$REPORTE»

log_success «Reporte generado: $REPORTE»

}

Esto parece cosmético pero no lo es. Cuando llevas 4 horas en una máquina y el terminal tiene 800 líneas de output, los colores y el formato te permiten procesar información más rápido. En un pentest real donde documentar es obligatorio, tener el reporte generado automáticamente con tus scripts de automatización te ahorra 30 minutos de trabajo manual.


Errores comunes en shell scripting para pentesting y cómo evitarlos

1. Scripts sin validación de permisos de root

Nmap con -sS (SYN scan) requiere privilegios de root. Si tu script de pentesting llama a nmap sin verificarlo, falla con un error críptico. Agrega esto al inicio de cualquier herramienta de hacking que lo necesite:

bash

if [ «$EUID» -ne 0 ]; then

echo «[-] Este script requiere privilegios de root para SYN scan»

echo » Ejecuta con: sudo $0 $*»

exit 1

fi

2. No manejar espacios en rutas o variables

Si el nombre del directorio de output tiene espacios, el script se rompe. Siempre pon tus variables entre comillas dobles: "$VARIABLE", no $VARIABLE. Parece obvio hasta que te pasa a las 2 AM.

3. Hardcodear rutas de wordlists

He visto scripts de GitHub que asumen que /usr/share/wordlists/rockyou.txt existe descomprimido. En Kali viene comprimido por defecto. Verifica siempre:

bash

WORDLIST=»/usr/share/wordlists/dirb/common.txt»

if [ ! -f «$WORDLIST» ]; then

log_error «Wordlist no encontrada: $WORDLIST»

log_warning «Instala wordlists con: sudo apt install wordlists»

exit 1

fi

4. Scripts sin control de errores en pipes

En Bash, por defecto, un pipe devuelve el exit code del último comando, no del que falló. Si haces comandoquefalla | grep «algo» y grep encuentra algo, el script asume que todo fue bien. Agrega esto al inicio de scripts de automatización críticos:

bash

set -o pipefail

Con eso, si cualquier comando en un pipe falla, el exit code refleja ese fallo.


Próximos pasos en automatización de pentesting

Si llegaste hasta aquí y ejecutaste los scripts, ya tienes una base funcional de automatización en shell scripting. El siguiente nivel natural:

1. Enumeración avanzada con scripts más complejos

Aprende a integrar herramientas como ffuf, nikto y enum4linux en tus scripts. En hackchest.net tienes guías específicas de enumeración por protocolo que complementan directamente lo que aprendiste aquí: Enumeración de servicios en Linux para pentesting

2. Scripting con Python para hacking

Una vez que tienes Bash sólido, Python te abre puertas que Bash no puede: sockets raw, manipulación de binarios, exploits personalizados. El salto es natural y mucho más fácil cuando ya entiendes la lógica de scripting: Python para hacking ético: primeros scripts

3. Automatización completa de CTF workflow

Combinar todo esto en un workflow completo para CTFs — desde el primer nmap hasta el reporte final — es el siguiente nivel de productividad. Hay un artículo en hackchest.net que cubre exactamente eso con ejemplos reales de máquinas de HTB: Workflow de pentesting automatizado para CTFs


FAQ sobre Bash Scripting para Hacking Ético

¿Necesito saber programación para aprender shell scripting para hacking?

No. El scripting en shell no es programación en el sentido tradicional — es automatización de comandos que ya conoces. Si sabes ejecutar nmap 192.168.1.1 en terminal, ya sabes el 60% de lo que necesitas para escribir un script de reconocimiento. El resto es aprender la sintaxis de variables y bucles, que se aprende en horas, no semanas.

¿Es mejor Bash o Python para scripts de pentesting?

Depende del contexto. Shell scripting es mejor cuando necesitas encadenar herramientas del sistema (nmap, gobuster, curl) y el script va a correr en cualquier Linux sin dependencias. Python es mejor cuando necesitas lógica compleja, manipulación de datos estructurados o librerías especializadas como scapy o impacket. Para empezar con automatización de hacking: Bash. Para crecer: los dos.

¿Estos scripts funcionan en Windows con WSL?

La mayoría sí, con matices. WSL2 ejecuta un kernel Linux real, así que Bash puro funciona perfectamente. El problema está con herramientas que necesitan acceso a interfaces de red raw, como nmap con SYN scan. En WSL2, nmap funciona pero con limitaciones en ciertos tipos de escaneo porque la interfaz de red pasa por una capa de virtualización. Para pentesting serio, usa una VM con Kali nativa o una instalación Linux real. WSL2 está bien para aprender automatización en shell scripting y desarrollar scripts, no para escaneos de producción.

¿Cuánto tiempo se tarda en dominar shell scripting para pentesting?

La sintaxis básica la tienes en un fin de semana. Escribir scripts funcionales para reconocimiento y enumeración, en 2 o 3 semanas de práctica constante en plataformas como HackTheBox o TryHackMe. El dominio real viene con la experiencia acumulada en máquinas reales: cada problema que resuelves con un script nuevo suma más que cualquier tutorial.


Todos los scripts de este artículo están pensados exclusivamente para automatización en entornos autorizados. Practica siempre en laboratorios propios o plataformas legales.