NoSQL injection in MongoDB
We all know that SQL injection (SQLi) is a thing. But it may surprise quite a few people that similar injection techniques are possible when the underlying database is a NoSQL database.
In this post, I’ll show a simple way of exploiting such a NoSQL injection in two ways.
Application
This attack can do at least the following:
- Bypass authentication
- Leak sensitive information
First, let’s look at authentication bypassing.
Hint: Code files can be found on my github.
Authentication bypass
Doesn’t this sound awesome? A simple trick to bypass authentication? Can it really be that simple? The short answer is: yes. Yes, it can be.
Let’s take a look at an authentication mechanism that uses the famous MongoDB:
After establishing a connection, this code tries to get the user from the database whose username and password match the POST parameters username
and password
. If such a user is found, “Login succeeded” will be displayed.
I know, this is not in any way sophisticated, but it helps bringing my point across.
Here’s the database:
How to bypass
Bypassing this is incredibly easy. Let’s do a proof of concept.
The Jupyter notebook I’m using here can be found on my github.
First, here’s a failing login attempt:
This, as expected, prints “Login failed” to the console. We will now bypass that login mechanism:
Yes, it is that simple!
We simply alter the parameters username
and password
to include expressions. In this case we’re using $ne, which means “does not equal”. So we tell MongoDB to find all users that are NOT called steps0x29a and DON’T have steps0x29a set as their password, essentially bypassing the login.
This can be used to bypass website login forms with burpsuite, for example. Simply tell burpsuite to alter all POST requests (or whatever is appropriate) to include [$ne]
in them and there you go.
Information disclosure
Bypassing a login form can be powerful in itself, of course. But as users often reuse their credentials, for example for SSH access, we might want to extract some real information from the database. The good news is: we totally can!
There’s another modifier like [$ne]
(actually, there are several, see MongoDB’s documentation for details): $regex
.
It works like [$ne]
, but matches data against a regular expression which we can control in our scenario. Yes, you read that right – MongoDB allows us to use regular expressions to leak information from it!
As this is a bruteforce approach, we first need to build a list of all characters that we want to try. Here’s how I did it, but you can (and should) build your own:
Python’s string.printable
provides all characters that Python deems “printable”. As we’re dealing with regular expressions, we need to escape some of them in order to make it work. That’s why I’m importing re
here, so we can use re.escape
later on.
Now on to bruteforcing a username:
Let’s go through this step by step:
In bruteforce_user
we start with a blank username (of course it’s possible to use a seed, e.g. “a” or “r” to nudge the algorithm in the right direction) and iterate over the alphabet one character at a time, escaping it with re.escape
.
We build a payload by appending the next (escaped) character we want to test to the part of the username we know by now (starting with an empty one).
We then send the payload to the server and check the response.
If the (bypassed) login is successful, we check whether the username actually exists (the bypass will succeed with “adm”, but the check function will not; it will, however, succeed with “admin”).
The test_username
function uses a slightly modified regular expression to verify usernames. We need it in order to recognize when we’ve identified a valid username.
That’s it. Passwords can be bruteforced the same way by simply swapping the parameters in the request and passing in the username as well:
That’s where I’ll leave this topic for now. Of course there’s a lot that can be improved and added to this code and it is far from fool proof for sure.
Check out the Jupyter notebook on my github to play with the code and have fun! Don’t do stupid stuff đ
Leave a Reply