🏛️Olympus
A custom CMS and a puzzle-like exploit chain with some SUID fun for privesc.
Last updated
A custom CMS and a puzzle-like exploit chain with some SUID fun for privesc.
Last updated
Room
Olympus
OS
Level
Medium
Link
Diving right in, we add olympus.thm
to the /etc/hosts
and start with a basic port scan.
We can now follow up on these two ports with a more in depth nmap
scan:
As with many other boxes we can quickly rule out ssh
as an entry point due to its version and the fact that the room description tells us that brute forcing any login is out of scope.
Hence, we're left with a fairly recent Apache webserver which looks surprisingly small at first glance: only a single landing page without links or much content.
In order to further enumerate the webserver we can fire up nikto
, though the scan doesn't really come back with a lot of information:
It does show the /static
directory but neither the particles library nor the CSS and images in there contain anything useful. Since there isn't really much to go with so far we'll start a gobuster
scan:
After trying multiple wordlists and extensions, the common.txt
yields an interesting path:
/~webmaster
-> navigating to it we are greeted by what looks like a sloppy custom CMS created by the challenge author himself.
The hygiene of this self made CMS seems pretty poor and while gobuster
continues to search for recursive directories we'll find that there doesn't seem to be much content on it. However, we do find multiple interesting input elements:
a search bar
a login field
a category URL parameter: http://olympus.thm/~webmaster/category.php?cat_id=2
Just out of curiosity let's try and search for '
to see if that breaks any potential query - and sure enough it does.
We could continue to look at the login form and the URL parameter, as well as the admin panel that we can reach with BurpSuite by ignoring the redirects back to index.php
in the location header, but while all of these are fun to play around with we'll stick to the SQL injection we got here.
Fortunately, the error message above is very verbose and we learn not just the DBMS but also an important bit of the query that's being generated. Analyzing the POST that is triggered by clicking on the search icon we could quickly come up with an sqlmap
command to exploit the SQLI automatically.
But that's no fun is it?
For the sake of practice, let's see how we'd go about exploiting this manually step by step.
Feel free to skip to the next chapter if you already got a database dump and want to continue with the CTF.
First of all, we'll start the BurpSuite proxy, catch a search query and send it to the Repeater tab so that we can test our queries efficiently.
The error message reveals that the SQL query in the background could look something like this:
SELECT post FROM table WHERE col LIKE '%<INPUT>%' AND post_status='publish';
Since we control the <INPUT>
and our goal is to build a working query, we'll have to
close the matching string with a '
put in any SQL query that we like - for example via UNION
disregard the rest of the query by commenting it with -- -
(the space is important for the syntax of a comment - the last dash is just for visibility)
With that in mind we can create and test a simple payload like this: ' UNION SELECT NULL-- -
.
We get an error that indicates a "different number of columns". This happens because the UNION
statement requires both the left and right SQL query to return the same amount of columns -> meaning that we will have to try again with more values: ' UNION SELECT NULL, NULL-- -
Increasing the amount of NULL
values one by one we find that with 10 values in our SELECT statement we finally receive no error and all posts are displayed.
For visibility we'll exchange the NULL
values with numbers and create a query that will yield no original post: x' UNION SELECT 0,1,2,3,4,5,6,7,8,9-- -
.
We can pinpoint the locations where our injected values are reflected on the website. For example 2
was probably the title
column, 3
the author, 4
a date and 6
the content. It seems that not every column is being reflected here but all we need is one for what we're about to do.
With the proof of concept working it's now time to get to the good stuff. Let's skip the version enumeration (@@version
for MySQL) and jump straight to listing the available tables with this query:
Let's put that query in field 4
and don't forget to URL encode the entire query (CTRL+u
in BurpSuite).
We can paste those table names somewhere else - format them - and search for interesting tables. chats
, comments
, posts
and users
seem pretty interesting but let's get the flag
first!
Having discovered an interesting table name we should now enumerate the column names to see what that table has to offer. For this purpose we can use the following query:
Again, pasting the query in any reflected position we get the result: flag
. That means we have a table flag
with a single column flag
. Let's extract that with (SELECT flag from flag)
.
From here, the process of enumerating and dumping a table just repeats over and over again (it's a good basic SQL practice).
We successfully used manual UNION based SQL injection to enumerate and dump a table from the MySQL backend database.
Whether doing this manually or with a tool like sqlmap
- we get a bunch of information from these tables. To keep things short, here are the interesting bits and pieces:
A user prometheus
with the password hash $2y$10$YC6u...REDACTED...Dvnj3C
2 more users with a salted password hash and the emails root@chat.olympus.thm
and zeus@chat.olympus.thm
respectively
A message about an uploaded file with the original name of prometheus_password.txt
but stored on the server as 47c3210d51761686f3af40a875eeaaea.txt
A mention of an upload folder
A mention of poor password quality for the prometheus
user
Since we're informed that prometheus
is using bad passwords and we found his password hash in the database, let's try to crack that. A quick search in hashcat
examples or haiti
reveals the type of hash:
Using john
or hashcat
and rockyou.txt
we can easily retrieve the password.
Unfortunately, the credentials don't work on ssh
. But we didn't encounter another login so far and we also haven't found the upload directory that was mentioned in the database yet.
So we're back at enumerating the webserver.
One thing we haven't tested for yet, are subdomains (i.e. other virtual hosts on the target). Let's attempt that with wfuzz
.
Et voilà, we get a 200
response for chat.olympus.thm
. Adding this to /etc/hosts
and visiting it we are greeted with a login form. How fortunate!
We try the credentials we found and gain access to the Olympus Chat App as prometheus
.
On a side note, we could've also deduced chat.olympus.thm
being a valid vhost by just looking at the email domains of the zeus
and root
user in the database.
Anyway, see the prometheus_password.txt
? Looks familiar because we already saw that being mentioned in the database dump of the chats
table. We could start a gobuster
scan in the background but common upload directories would be /upload
or /uploads
and by testing them manually we rapidly find that /uploads/
actually exists.
Trying to access prometheus_password.txt
fails but we know from the database that the file was renamed to 47c3210d51761686f3af40a875eeaaea.txt
-> and that does exist.
The file itself doesn't contain anything useful but now we know where uploaded files are stored and how to retrieve the uploaded files name.
The Olympus Chat App does not provide a lot of interaction. We can send messages and upload files or log out and reset our password.
Although we can easily test for XSS on the messages (yes, it's possible) the file upload is much more interesting. Let's just dive right in and upload a standard php reverse shell. Fair enough, no filter, no errors - the upload was successful.
Using sqlmap
we can determine the file name of our uploaded reverse shell.
In my case it's at chat.olympus.thm/uploads/e90a754682b2fd927a16491b085e7872.php
.
With access as www-data
our next step will be to escalate privileges.
www-data
is not part of any interesting groups, has no interesting files in his home (except one directory which is owned by root
and zeus
but that might be important later) and only restricted access to the home
folder of a user named zeus
.
Once we get to check for SUID binaries though, we get something interesting:
A custom looking binary that's owned by zeus
and has the SUID bit set. Simply executing it we can see that it can be used to copy files from any source to any destination with the permissions of zeus
. Additionally, the copied file will be equipped with the octal permissions 0666
, i.e. read-write for everyone.
Since ssh
is running and we can see a .ssh
directory in zeus
home folder we can attempt to extract his private ssh key this way (assuming he didn't remove or rename it and that it's valid).
Saving it on our Kali and connecting to ssh
we realize that it still requires a password though. But leveraging ssh2john key
and then using john
with the wordlist rockyou.txt
on the resulting hash, we're able to extract the password quite easily. And finally, we can access the machine via ssh
as zeus
.
We compromised zeus
and can now submit the second flag.
Now that we are zeus
we can come back to the weird directory in the /var/www/html/
folder that we found earlier. (And if we weren't curious back then, we could have found it by searching for group accessible files now.) In there we find a weird looking php
file. Let's see what it does.
At the very beginning of the script we got a form that checks for a password. Fortunately for us, the password is put there in plaintext. Accessing the form via the browser and utilising the password we get this:
It appears we've discovered prometheus
backdoor. The script is kind enough to let us know how to get a shell so we follow the instructions and gain root
access.
We succesfully compromised root
and can submit the third flag.
As we saw in the final hint beneath the root
flag prometheus seems to have hidden another flag on the server somehwere. For this part we can use a common grep
command that i'd usually use for password hunting:
grep --color=auto -rnw / -Iie "flag{" 2>/dev/null
We can read the.b0nus.fl4g
file and submit the last flag.
This box has been more like a puzzle than a realistic target and was very well prepared by the author to showcase quite a few vulnerabilities. However, if i were to mention the main issues i think we'd have:
Severe web-vulnerabilities including SQLI, XSS, Arbitrary File Upload and Broken Authentication (being able to see the admin panel even though we're not logged in)
Most of these stem from using unsanitized user input or missing filters -> never trust user input of any form and use proper input handling and filters
Weak passwords (although the passwords were stored in encrypted form, we were able to crack them) -> enforce a stronger password policy
Insecure application permission -> remove the SUID bit if it's not absolutely necessary
Insecure file permissions -> apply the principle of least privilege
Linux