GeminiV2 Walkthrough
This is a walkthrough of the CTF machine “Gemini2” on Vulnhub. A tough VM, with lots of learning potential!
****Spoiler Alert**** ****Spoiler Alert****
I seem to always be doing these CTFs in reverse order. I’ll be going back to do GeminiV1 after this, but for me this was very challenging and fun. I learned from both a web application and privilege escalation perspective as this one seemed to be very real-world based. So let’s get going!
The Nmap output looks to be limited to only SSH and HTTP, so let’s see what the webpage is serving up.
Ok, we have a page with uses that are apparently locked to an authenticated session (i.e. export of the profile, accessing the user list etc.). What about Nikto?
Wah-wah. Not really that useful. I was getting similar results using dirb, and using a longer wordlist was taking too long, so I switched to dirbuster (GUI) and found some interesting files:
I’m not really seeing any other angles of attack at the moment, so let’s head on over to regisration.php and see if we can register a user:
The registration process here is simple until we’re hit with:
I only had to guess the activation site (activate.php), but upon landing, along with the activation code, it is asking for the user “id”. Luckily, I had already noticed this in the URL after registering as it gives a profile.php?u=16. You can change this to iterate over other user IDs as well, but for this instance we only needed to know ours so we can activate our account.
The activation error has given the type and length of code we’re expected to have (“6 digit”).
So first off I wanted to create a database of every possible 6 digit code combination and Crunch is a great tool for that, which didn’t take more than a couple of seconds to run and create:
Next, I need to find a way to “feed” these one at a time to the activation form. Let’s look at the activation request in Burp Suite to see what we’re dealing with:
So, it looks like we’re going to have a CSRF token to contend with here. With an incorrect activation code, we will also recieve a “403 INVALID VALUE” response from the server (as seen below):
To get started I exported the original POST request I had in Burp, as a Curl command. From that point I was a bit stumped and truely was not sure how to bypass the CSRF token. In need of some direction/inspiration, I ended up watching a bit of the walkthough from the creator of this CTF I was pleased to see him perform the exact same Curl export that I was stumped on, so when I saw him grep the token, I knew what I was missing, stopped the walkthough and finished the script I had began:
Is this script ugly? Oh yeah. Does it work? You bet. I echo’d the token and code just to ensure both were random for each request. Running the request through Burp made searching for the correct code extremely easy, as I was looking for the only non-403 value present:
As you can see, the only non-403 code was a 302 (presumably activating and redirecting to the user’s home page), using activation_code 000511. Since our account is now activated we can export our profile to PDF, or view the complete user list:
It doesn’t look like much is here, so let’s browse the source just to be sure:
Ok, it looks like we have a hashed password for the admin account. Let’s see if we can crack it with HashCat:
Perfect, now let’s login as Gemini and see what our options are!
Great, we do get an added “Admin Panel” with the option to execute commands. However when we try to do so, nothing happens. Upon further inspection in Burp we can see the following:
Ok, so it looks like we’ve hit a web application firewall (WAF) of sorts. Searching on ways to bypass using Burp Suite we’re directed to the following site
So assuming the WAF will allow bypasses to localhost, we add the following proxy options:
Going back now we’re able to successfully access our command execution page (although it’s a bit of a blind execution):
It also looks like there is some input validation for command execution going on:
So, after much trial and error I found that spaces were the main character that was causing me failure (in addition to other characters not being allowed). This was if the blacklisted character was encoded or not. I ran a search then on how to execute commands without using spaces and ran accross instances using brackets “{}” which were also illegal here. I then found references to the Internal Field Separator (IFS) that is used in Bash to split lines into words. This meant that if you specify the deliniator and use it in an IFS statement, you could then create a series of commands using that deliniator and IFS would expand the command.
Unfortunately I had to also refer to the walkthough on this one. Although I was sure that the IFS option was the way to go, the exact syntax elluded me. The following is what I used and does make sense once seen:
With a NetCat listener running on 4444, that last command triggered the reverse and I had a limited shell running under the Gemini1 account.
Enumerating the local machine from here was not trivial and took different avenues. I did end up settling on the Redis-Server as the main area of focus for privilege escalation since local files could be written using the redis-cli tool. Since the server was running under root, we could take advantage of the exploit.
Next after looking up the command syntax and frequently used redis-cli commands I checked to see if a password was required/set in the config file:
Great! Now all we need to do is follow the exploit, making sure to target the “/root/.ssh/” directory for the config. I first created my new SSH keypair and ran the following redis-cli commands:
After this I thought I was home free and did a congratulatory ssh root@localhost waiting for my root prompt. Nope. I was prompted for a password. In my haste I forgot a pivotal step. My new SSH keys that I created earlier were not in my own “.ssh” folder! After quickly moving them and retrying my command (not so confidently this time), I was greeted with:
Phew! Ok let’s grab the flag now:
I usually try to stay clear of the walkthoughs while going through these, but I think it’s detremental to the learning process to, at some point refer to them if you are not progressing any further. Progress is always forward, and if you are stuck, and have been stuck in a position for awhile then there is no progress and the learning has stopped. The references I’ve made above (and will most-likely continue to make) are for those specific instances only and generally I do try to come up with variations from what I have found, or other ways of performing similar tasks to continue to think outside of the CTF or walkthough. This keeps the learning process going, and is what I have found helpful.
Happy Hacking (⊙_◎)