IceCTF 2016: ChainedIn (75 points)

It’s already been 1.5 month since IceCTF took place, but I recently stumbled upon a similar challenge at an offline CTF. Therefore, I chose to write this write-up anyway.


I keep getting so much spam from this website. Can you leak the admin password so I can put a stop this nonsense? I made an account for you to help you break in, the username is agent1568 and the password is agent1568


After opening the website that was given with the challenge, I was presented a simple-looking website. Of course, I tried to log in with the credentials provided in the description. After logging in, there was only a text:

Nothing more, nothing less. It seemed that this was the only interaction I was going to get from logging in. As the challenge said the admin account had to be breached, this was the point where some kind of an injection, or at least some messing around with parameters, would have to be done.

As I always proxy my browser’s requests through Burp during CTFs, I quickly figured out that the requests were done in JSON. The two images on the homepage also showed something about MongoDB and AngularJS, so I figured the backend system was running MongoDB indeed.

After a quick Google search, I stumbled upon this website that described how a MongoDB injection was possible by using nested object within the form fields. Normally, the credentials would be passed through to the server like this:

Now, if the calls are not properly sanitized and the system is poorly configured, it is possible to not only pass on a string like “admin_pass” as a password, but a JSON object instead. Using this technique, we can make a request like this:

As you will probably see already, I used MongoDB’s $regex operator above (click here for the official documentation). Instead of comparing the true password of the user admin with a user-provided string, it will match it with our regular expression, which consists of an ‘a’ only in this example. If the admin’s password contains an ‘a’, the database query looking for the admin user + its password would return a record, or True, enabling us to log in as admin.

It turned out this approach worked, indeed. After repeating the request with the parameters in the example above, I got the following message:

Mm, no flag there. Could it be that the password is the flag? If so, it must start with IceCTF{. A quick test showed that this indeed was the case.

We now have the first part of the admin password (the flag), so we can now try to append a character each time. If the guessed character is correct, we can expect the message ‘Welcome back Administrator!’ to show up. If it is not correct, we will see another message (which is “Invalid credential !” by the way). Looking at the other flags, it will likely consist of both lowercase and uppercase letters, the numbers 0-9, the underscore (_) symbol to separate words, and a closing curly bracket (}) to end the flag.

To reduce the number of unnecessary tries, I wrote a script that compiled a list of all unique characters present in the password first. Using that list, which I called test.txt, I let another script guess the next character of the password recursively, starting with “IceCTF{“:

Let’s try to run the script!

That was the MongoDB injection! The flag is IceCTF{I_thOugHT_YOu_coulDNt_inJeCt_noSqL_tHanKs_monGo}.




Leave a Comment

Your email address will not be published.