Day seven in the Advent of Cyber 3 (2021). Again, Grinch Enterprises has been at work taking over systems from The Best Festival Company. The development team that handles gift requests from children migrated over to a new technology, but in doing so forgot to patch the system and left the application vulnerable. Grinch Enterprises used that vulnerability to take control over the applications. They didn't patch either, so we can overtake the system yet again, using the same vulnerability.
WARNING: Spoilers and challenge-answers are provided in the following writeup.
Official walk-through video is as well available at TryHackMe - Advent of Cyber 3 - Day 7 Walkthrough.
Day 7 - Migration Without Security
The challenge today is all about NoSQL - https://en.wikipedia.org/wiki/NoSQL. In short terms, NoSQL is a non-relational database-structure. Knowing MySQL and MSSQL being relation-databases where the data is structured in tables, rows, columns and having relations in-between, the concept of non-relational databases is not far off. NoSQL is parted into some categories as "key-value store", "document store", "graph" and "object store" all having different pros and cons.
Looking at the specific MongoDB, which is a NoSQL Document store-database, the data consists of "Collections" which are similar to tables/views in relational-databases, "Documents" which are similar to rows/records in relational-databases and "Fields" which are similar to columns in relational-databases.
The Challenge
After starting the challenge-machine, we log on the the machine using SSH
. We are tasked to "interact with the MongoDB server to find the flag". So firstly we start the interactive console for MongoDB on the server via the command mongo
. Then we show all databases via the show databases
command. Here we see a rather suspicious database called "flagdb" - lets try see what's in that. We switch to the database via the use
command and then uses db.getCollectionNames();
(remember that MongoDB commands is case-sensitive) to show all the collections and behold - "flagColl" sounds interesting to us. With db.flagColl.find();
we can retrieve all the document objects for that collection, and we have found the flag.
The next question is yet again a flag we need to find on the application-webpage.
We do not know the password, but are told the user is "admin". With the knowledge of the application running with a MongoDB in the backend, we can use a NoSQL injection to circumvent the authorization logic. At least if the user-supplied data is not fully escaped. To do so, we set up Burpsuite to proxy the request from the login-page where we try to login with the username of "admin" and a random password of "admin".
As showed is the picture below, we intercept the request and change the POST
-data before sending the request. We do not know the password, but what if we could change the logic from testing the provided password to be excactly as in the stored database, but to check if the provided password is not the same as in the database? We can do this by adding [$ne]
to the end of the password
parameter - this instructs MongoDB to go from "is equal" to the provided "not equal".
And with that, we are logged in and greeted with the dashboard. Just a quick click on the "Flag!"-link and we have the answer for the next question.
For the next question, we are going to perform more NoSQL injection - this time by exploiting the "Search" page, where we are tasked to list all usernames that have the role "guest".
First we try with the same operator [$ne]
as we used in the login-injection. But that wasn't successful. The input from the search-field seems to be escaped or at least we need to "de-escape" before sending the data. But luckily we see that the information is provided back to us as GET
-parameters. This we can use more directly.
Okay, so to use this, we use the same operator on the username
field the same way as we did before and then add a role
parameter with the value of guest
as provided in the question. And with that, we have the next flag for the challenge.
Last question for the challenge is to retrieve the user record for the specific user mcskidy
using the same technique. So this time we specify the username as requested and then just use the MongoDB [$ne]
operator on the role
parameter, setting it to something random.