Creando nuestros propios escáneres en bash

Descripción de la publicación.

5/12/202511 min read

Accedemos como ya sabemos al siguiente usuario. Bandit16 con su respectiva contraseña, con el siguiente comando:

$ sshpass -p 'kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx' ssh bandit16@bandit.labs.overthewire.org -p 2220

Y volvemos a hacer export TERM=xterm para poder limpiar la terminal sin problema con CTRL + L es decir, cambiamos la terminal actual por xterm.

Ahora volvemos a la página de bandit a ver que nos indica. Y como vemos nos dice que la contraseña se aloja dentro del nivel actual dentro de algún puerto del host local en el rango 31000 al 32000 Vamos a comprobarlo...

Entonces lo que haremos será crear un archivo dentro de nuestra máquina llamado portScan.sh ( $ touch portScan.sh ) Y le daremos permisos de ejecucción $ chmod +x portScan.sh Y como podemos comprobar ahí lo tenemos.

Bien llegados a este punto, vamos a volver a aplicar la función Ctrl_C Como vemos en la imagen, para poder capturar la tecla CTRL + C Y poder salir del script. Así mismo agregando en la primera línea #!/bin/bash para indicar que se trata de un archivo bash

Ahora para empezar a crear el escáner. Deberíamos empezar por crear una secuencia donde se detecte desde el puerto numero 1 al último puerto, que sería el 65535. Por lo tanto haremos seq 1 65535 como vemos en la imagen.

El resultado sería el siguiente que vemos en la imagen superior. Nos crea un listado de todos los números del 1 al 65535.

Aplicaremos la siguiente regla: for port in $(seq 1 65535); do donde indicamos con for que para la variable port su valor sea igual al comando $(seq 1 65535) y que una vez almacenado dicho comando en la variable port Podamos utilizarla mediante do, junto al comando echo -e "\n[+] Estamos en el puerto $port" Donde hacemos un llamamiento a la variable port previamente definida. Para que a medida que se van imprimiendo los números del 1 al 65535 nos añada [+] Estamos en el puerto 1 , [+] Estamos en el puerto 2, [+] Estamos en el puerto 3.Y así sucesivamente, como veremos en la siguiente imagen... Finalmente añadiremos un done para indicar que ahí acaba nuestra función.

$ bash Bien ahora voy a explicar como podríamos detectar si un puerto esta abierto, o está cerrado de la siguiente manera.

Primero: $ bash Iniciamos la terminal bash para poder aplicar el siguiente comando

Segundo: $ echo ' ' > /dev/tcp/127.0.0.1/22 Donde indicamos con echo ' ' que queremos enviar una cadena vacía > al archivo /dev/tcp/127.0.0.1/ Este es un archivo o ruta especial /dev/tcp/ donde dentro se encuentra el local host ( 127.0.0.1 ) Y justo dentro podemos seleccionar el puerto que queramos del 1 al 65535 y comprobar mediante el output si se encuentra abierto o si se encuentra cerrado

Tercero: si el puerto se encuentra abierto y si verificando su código de estado vemos que el código de estado es igual a 0 Será exitoso.

Cuarto: En caso contrario si el código de estado NO es exitoso, el código de estado es incorrecto, es decir igual a 1

Quinto: Esto lo podemos verificar con el comando $ echo $? Tal y como vemos en la imagen superior

Ahora llegados a este punto. Sabiendo como detectar si un puerto está abierto o cerrado. Vamos a jugar con los operadores && y || que vimos al principio del curso. Donde con && indicamos que si el comando que hay a la izquierda se ejecuta con éxito, entonces ejecutamos el siguiente, es decir echo -e "[+] El puerto esta abierto". Y del caso contrario con || si el código NO se ejecuta con éxito ejecutaremos echo -e "[+] El puerto esta cerrado" Tal y como vemos en la imagen.

Pero tenemos un problema. Que si el puerto esta cerrado, vemos STDERR como output, entonces vamos a aplicar (echo ' ' > /dev/tcp/127.0.0.1/23) 2>/dev/null Y poniendo entre paréntesis el comando echo como vemos en la imagen. Para enviar todo el flujo STDERR al archivo /dev/null.

Entonces como output veremos lo siguiente:

$echo ' ' > /dev/tcp/127.0.0.1/22 && echo -e "[+] El puerto esta abierto" || echo -e "[+] El puerto esta cerrado"

[+] El puerto esta abierto

$(echo ' ' > /dev/tcp/127.0.0.1/23) 2>/dev/null && echo -e "[+] El puerto esta abierto" || echo -e "[+] El puerto esta cerrado"

[+] El puerto esta cerrado

Ahora, llegamos a la parte interesante. Una vez vistos los conceptos anteriores. Sabiendo que es un puerto "por encima", sabiendo como detectar si un puerto está abierto o cerrado. Aplicaremos la misma operativa que antes. Eliminamos el echo que teniamos en la función for. Y aplicamos la siguiente línea:

(echo ' ' > /dev/tcp/127.0.0.1/$port) 2>/dev/null && echo -e "[+] $port - OPEN"

Donde aplicamos (echo ' ' > /dev/tcp/127.0.0.1/$port) 2>/dev/null Donde entre paréntesis aplicamos el envió de una cadena vacía con echo hacia el archivo /dev/tcp/127.0.0.1/$port Donde $port es la variable que hemos guardado anteriormente del 1 al 65535 por lo tanto nos buscará todos los puertos dentro de este rango.

Y ¿Porqué lo ponemos entre paréntesis? Porque así todo el flujo STDERR lo podemos enviar al /dev/null por lo tanto 2>/dev/null Seguidamente aplicamos lo mismo que antes && el operador and para que si el primer operando es exitoso se ejecute el segundo operando, es decir echo -e "[+] $port - OPEN" Donde le indicamos que a medida de que el código sea exitoso, muestre como output el numero de puerto y OPEN. Tal y como veremos en la siguiente imagen.

Como vemos al ejecutar el escáner, nos indica el puerto 22 y el puerto 53, vamos a comprobarlo...

Y así es, como vemos está abierto el puerto 53 y el puerto 22

Para que el escáner sea más rápido, podemos aplicar la técnica de los HILOS, esto se aplica para que en lugar de que vaya comprobando de 1 en 1 los puertos abiertos, pueda ir comprobando todos los puertos de manera paralela al resto si están abiertos o no, sin tener que depender de un orden de espera. Se aplica al final del comando como vemos es el símbolo &

(echo ' ' > /dev/tcp/127.0.0.1/$port) 2>/dev/null && echo -e "[+] $port - OPEN" &

Y al final lo que haremos será añadir done; wait Donde con wait lo que haremos será esperar a que los hilos finalicen. Y con esto debería ir más rápido nuestro escáner.

Para que podáis entender mejor que es esto de los HILOS. Vamos a realizar una copia del archivo portScan.sh al archivo hostScan.sh

Vale, llegados a este punto. Para que se pueda entender mejor. Vamos a explicarlo con las direcciones IP. Como ya sabemos cada equipo tiene su propia dirección IP. Esta se puede comprobar utilizando el comando $ ip a Y como vemos mi IP es la 192.168.1.91, como vemos en la imagen en la parte superior izquierda. Nosotros podemos realizar un escaneo de red para poder ver que hosts es decir máquinas en nuestra red o bien IP's se encuentran activas y cuales no. Entonces podemos utilizar un comando muy común como el comando $ ping -c 1 192.168.1.1 Donde ping es una función para enviar paquetes a una máquina. Con el parámetro -c 1 le indicamos que queremos enviar solo 1 paquete a esa máquina Y seguidamente adjuntamos la dirección IP hacia la que queremos enviar dicho paquete.

Esto nos va a responder con el output del comando ping. Por lo tanto para que podáis ver como podemos realizar un escaneo con bash, vamos a enviar todo el output al archivo /dev/null con el parámetro &/dev/null como vemos a continuación. Y seguidamente vamos a aplicar la misma sintaxis que hemos aplicado anteriormente con el archivo portScan.sh. Aplicaremos los operadores && para indicar que si el operativo anterior es exitoso, ejecute el comando echo -e "[+] El host esta activo". Y en caso contrario con el operando || indicamos que si el operativo anterior NO es exitoso ejecutaremos echo -e "[+] El host NO esta activo"

Entonces por ende, como vemos de output en el primer comando hemos cambiado la dirección IP por esta 192.168.1.1. Entonces el output dice que el host esta activo. Por lo tanto si que existe

Y como vemos en el segundo output, hemos puesto la dirección IP 192.168.1.5. Como no existe, nos dice que el host NO esta activo.

Vale, ahora, como podemos ver, al realizar el comando anterior, en el momento en el que el host NO esta activo, el output tarda bastante en darnos una respuesta. Un host cuando esta activo normalmente no tarda nada en responder, sino que te lo reporta al momento. Entonces lo que aplicaremos será el comando timeout al principio, con tal de indicarle que a todo el comando ping quiero que, con el parámetro 1, le des un tiempo de vida de 1 segundo. Con tal de que si esta activo nos lo reporte al momento, y en caso contrario no tarde tanto en responder, y salte directamente El host NO esta activo. Seguidamente el parámetro bash -c para indicarle que trabajamos sobre un comando escrito en bash.

Bien, ahora como sabemos de IP en la red local tenemos muchas, desde la 192.168.1.1 a la 192.168.1.255, de la 192.168.2.1 a la 192.168.2.255 y así hasta la 192.168.255.255. Y muchas más que podemos configurar manualmente. Pero en está ocasión únicamente utilizaremos de la 192.168.1.1 a la 192.168.1.254 para nuestro escaneo, ya que la 255 en este aspecto no nos interesa, así que utilizaremos hasta la 254.

Vale, lo que haremos seguidamente será editar el archivo para poder adaptarlo al escaneo de host's. Primeramente en la variable for aplicaremos for i in $(seq 1 254); do Donde la variable i es igual al comando seq 1 254. Y de está manera se guarda para poderla usar próximamente.

Seguidamente aplicaremos el mismo comando que vimos anteriormente timeout 1 bash -c "ping 192.168.1.$i &>/dev/null" donde con el parámetro 192.168.1.$i le indicamos que va a utilizar todos los números del 1 al 254 con tal de que se realice un ping a todos los equipos del 1 al 254 como vimos anteriormente. Sumándole el operando && para indicar que en el caso de que el código de estado sea exitoso, se ejecute el siguiente comando echo -e "[+] HOST 192.168.1.$i ACTIVE"

Ahora lo que haremos será ejecutar el script ./hostScan.sh Y como podemos observar va muy lento a la hora de buscar direcciones IP. Por lo tanto aplicaremos los HILOS como ya sabemos, de la siguiente manera...

Agregaremos al final del comando timeout el parámetro & Para indicar que queremos aplicar hilos sobre esta línea. Esto quiere decir que a medida que va escaneando una IP no hace falta que acabe para poder iniciar otro escaneo de otra IP diferente sino que va a realizar el escáner en paralelo sin necesidad de que exista una cola. Sino que realizará todo el escaneo de cada IP al mismo momento. Y con el parámetro wait al final, al lado de done para indicar que queremos esperar cuando finalice.

Y como vemos si volvemos a ejecutar otra vez el script, nos va a reportar todas las IP activas al momento.

Otra cosa molesta que podemos ver a la hora de ejecutar el script, puede ser. El cursor, tal y como vemos al final de la imagen. Este podemos ocultarlo de la siguiente manera...

Podremos ocultar el cursor aplicando el comando tput civis antes de la variable for como vemos en la imagen para ocultar el cursor. Y para poder volver a recuperarlo ya que sino, no tendremos cursor. Aplicaremos el comando tput cnorm justo debajo de done; wait

También agregaremos tput cnorm; justo delante del exit 1 para indicar que si realizamos un CTRL + C Y no llegamos a finalizar el script por lo que sea, que nos devuelva el cursor.

a screen shot of a computer screen showing a screen shot of a screen with a
a screen shot of a computer screen showing a screen shot of a screen with a

Y como vemos si volvemos a ejecutar el script, no va a aparecer el cursor.

Bien, ahora que ya hemos entendido este concepto, vamos a aplicarlo a nuestro ejercicio, como vimos con anterioridad. Nos volvemos a conectar al usuario bandit16 vía ssh con el comando pertinente

sshpass -p 'kSkvUpMQ7lBYyCM4GBPvCvT1BfWRy0Dx' ssh bandit16@bandit.labs.overthewire.org -p 2220

Volvemos a aplicar export TERM=xterm para poder limpiar la terminal con CTRL + C

Ahora lo primero que haremos será acceder al directorio tmp, con el comando $ cd /tmp/

Aplicamos el comando mktemp -d para poder crear un directorio de trabajo temporal, como vemos en la imagen.

Y accedemos a dicho directorio. $ cd /tmp/tmp.3fsiXqVhD5

Lo que haremos ahora será crear el script con $ touch portScan.sh y lo editaremos con nano portScan.sh

Lo que haremos ahora será crear el script con $ touch portScan.sh y lo editaremos con nano portScan.sh