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!

GeminiV2 NmapOutput

The Nmap output looks to be limited to only SSH and HTTP, so let’s see what the webpage is serving up.

GeminiV2 BasePage

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?

GeminiV2 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:

GeminiV2 Register

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:

GeminiV2 Registration

The registration process here is simple until we’re hit with:

GeminiV2 Register_Noactivate

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:

GeminiV2 Activate_Dic

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:

GeminiV2 Activate_Req

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):

GeminiV2 Activate_Res

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:

GeminiV2 CSRF_Bypass

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:

GeminiV2 Activation_Code

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:

GeminiV2 User_List

It doesn’t look like much is here, so let’s browse the source just to be sure:

GeminiV2 Admin_Pass

Ok, it looks like we have a hashed password for the admin account. Let’s see if we can crack it with HashCat:

GeminiV2 HashCat_CMD GeminiV2 HashCat_Pass

Perfect, now let’s login as Gemini and see what our options are!

GeminiV2 Admin_Panel

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:

GeminiV2 WAF

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:

GeminiV2 WAF_Bypass

Going back now we’re able to successfully access our command execution page (although it’s a bit of a blind execution):

GeminiV2 Blind_Execution

It also looks like there is some input validation for command execution going on:

GeminiV2 Input_Validation

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:

GeminiV2 IFS

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.

GeminiV2 Redis_Run

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:

GeminiV2 Redis_Config

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:

GeminiV2 Redis_Ex

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:

GeminiV2 Root

Phew! Ok let’s grab the flag now:

GeminiV2 Flag

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 (⊙_◎)