The first step, as (almost) always, is to enumerate any open ports on the machine.
Only 22 and 80 are open, so let’s continue to enumerate and see what we can find on port 80. It appears to be a page for the “Freeeze” frozen yogurt shop. Everything is static except for the blog posts, which have URLs of the form: http://charon.htb/singlepost.php?id=10
. Simple manual testing indicates that this is vulnerable -
so let’s put sqlmap on the case, and keep moving forward:
(Bizarrely, sqlmap fails on this simple injection. In any case, this database isn’t useful to us.)
Moving onwards, what should stick out to you is that the footer indicates this site is powered by “SuperCMS.” That means we should definitely start looking for the login portal for “SuperCMS.” This doesn’t appear to be an actual CMS system, so we’ll have to fall back to dirbuster to enumerate. I used the default wordlist directory-list-2.3-medium.txt
which pretty quickly hits /cmsdata/login.php
.
This leads us to a login page that appears not to be vulnerable to SQL injection, and a “Forgot Password” page that looks like it might be. The reasoning here is that the Login page returns the same error messages no matter what is passed, and has no discernible blind SQLi vulnerabilities. Meanwhile, the forgot password page gives at least 2 different types of errors:
' -> Incorrect format
[email protected] -> User not found with that email!
A handy trick for running / debugging sqlmap is to run it through Burpsuite:
sqlmap comes back with a potential blind SQLi vulnerability:
but something that sticks out right away are the responses for UNION based injections:
Their response size and error message were drastically different than the rest, so let’s take a closer look.
Working our way down the WAF Bypassing Strings list, we quickly find that changing the casing on UNION
gets us past the error. Using the limitations that we know of (the queryset must return an email), and expanding the union count, we hit the jackpot on:
' UnION SELECT '[email protected]', '[email protected]', '[email protected]', '[email protected]
The next step is to subsitute different values for [email protected]
to see what gets echoed back to us and what has to be an email. After a short period, we quickly find this:
' UnION SELECT '', (payload), '', '[email protected]
.
From there we either manually query the database, or use our favorite tool, but we can quickly get the list of users and passwords (there are some other tricky aspects to this SQLi like dummy data, orderings, etc., but I’ll leave that to the reader as an exercise):
super_cms_adm / tamarro
After logging in, there a few possible vulnerabilities: we can edit existing pages, create new pages, and upload images. Let’s take a look at the image upload first. After doing a few probing tests, it’s discovered that there is both client and server-side checks to make sure we’re uploading an actual image, and that the extension is that of an image. Right when we’re about to call this a dead end, we inspect the HTML source and see something funny:
dGVzdGZpbGUx
looks a lot like base64, and when we decode it, we get testfile1
, so clearly this is a tool for testing the upload. What happens when we decode it, give it a value, and try to upload something (I took a Blank.png file and inserted a reverse PHP shell into the middle of it to bypass the image restrictions):
It renames the file for us! This lets us rename our “image” to a .php
file and the web server will execute it as PHP and give us a reverse shell.
Once on the box, we quickly cd
to /home/decoder
and find a public key and encrypted password.
This is an extremely short key, and is trivially breakable (via something like RsaCtfTool). Once we break it and get the private key, we can decrypt pass.crypt
which gives us the ssh password for decoder.
Now we can SSH in as decoder, cat user.txt
and begin to think about priv esc. One of my first steps during priv esc is always sudo -l
and to look for SUID/SGID binaries:
supershell
is obviously very suspect here, and is our most likely route to root. Let’s try to figure out how this works:
So, it’s making sure we’re only running /bin/ls
and that our input doesn’t contain any of |&><'"\\[]{};#\`
. To get around this requires a little bash knowledge, and a little creativity. First, it’s pretty obviously missing a 3 big characters from it’s blacklist: $()
. This lets us execute a command before ls
runs. After doing a few local tests, it seems ls
outputs the full file contents of a file if you try to list it:
From there, it’s simple: