4 Common Misconceptions About Security That Hackers Hope You Don't Know

Dawid Esterhuizen

#MongoDB World#Security

I’ve always thought hacking was harder than it looks on TV. But after two years exploring the world of ethical hacking, I’ve learned that almost anyone can hack almost anything if they have sufficient knowledge and think creatively.

Practically every week, we hear about another data breach at a large organization or a new vulnerability in a widely used software package. Many of these exploits are the result of misconceptions about security, which often lead to security misconfigurations. In this post, I'll cover the four most common security misconceptions and explain how hackers leverage them to execute attacks. I'll also explain how MongoDB can help you protect your data against these attacks.

Watch Dawid Esterhuizen's MongoDB World 2022 presentation, Hack the MongoDB Planet!

1. NoSQL Injection

The first rule of secure web development is: Never trust user input. This brings me to the first common misconception:

MongoDB doesn’t use SQL, so I don’t have to worry about SQL injection.

I’ve spoken with countless developers who have this false sense of security. The truth is, as NoSQL databases gain an increasing share of the database market, attackers are starting to pay attention, and new exploit tools are starting to emerge, like NoSQLmap (a NoSQL version of SQLmap), which allows hackers to perform automated NoSQL injections on vulnerable applications and endpoints. But enough theory. Let’s start hacking (ethically).

Shown below is an example of a vulnerable application endpoint. The application uses the req.query.user and req.query.pass, which were provided by the user, as the values for name and password. The query string takes the username and password, builds a query, and checks to see if the user exists.

app.get('/', async (req, res) => {
 query = {name: req.query.user, password: req.query.pass}

 user = await client.db("secret_bank").collection("users").findOne(query)

 if (user){
   res.send('Success')
 } else {
   res.send('Failed')
 }
}
Vulnerable application endpoint.

This is a fairly basic authentication method, but one that can be easily exploited with some command line tools.

If you enter the correct username and password information, you can see the presence of strings on the server. (I’ve added some extra logging so you can see what happens on the server.)

Normal login.

The username and password are confirmed on the server and everything seems normal.

MongoDB queries are usually built with objects and arrays. The question from an attacker’s point of view is, can they inject those onto the server?

One of the interesting and not-very-well-known features of URL query parameters is that if you add a square bracket to a parameter in the URL, it is converted into an array. As you can see from this example, I added the password, notRight, as an array on the server.

Add square brackets to the parameter to see the presence of an array.

Say you’re an attacker and you want to inject a list of two values. You just have to do it twice with the same parameter and you’ll get an array list of values on the server.

If you add square brackets to the same parameter twice in the command line, you'll get an array list of values on the server.

This would definitely be useful for an attacker seeking to inject NoSQL into the application.

The next question an attacker might ask is, can they inject an object on the server? In any programming language, if you set a field name inside the square brackets you get an object. Here, you see the same with an object on the server.

If you set the field name inside square brackets, you'll see the object on the server.

So the attacker can now send objects to the server, but how do they exploit that? In an SQL injection, the most basic authentication bypass you can do is quote (") or one equals one (1=1) double dash. This query results in true every time.

Bypass login in SQL.

The SQL query above will evaluate if the user is equal to admin, which in our case is true. Then it checks if the password is equal to an empty string (due to our quote), or if one is equal to one, which is always true. The query will therefore always return the ID of the username if it exists. There are a few NoSQL options that will do the same.

If your password is actually set, you can run a query that checks if it's greater than nothing, which it always is, and use that to bypass authentication.

Similar to an SQL injection, there are a few NoSQL queries hackers can run to bypass application authentication.

This is a vulnerability in the application, not the database. The application assumes that the user is sending a string for the password and user. If the application forces the password and username to a string with .toString(), no matter what input the user gives, it is not parsed.

A lot of this is pretty obvious, but let's take it a step further. Shown below are a few lines of Python script that iterate over some characters and play a little with regex, and then do some blind NoSQL injection. By doing that, I'll demonstrate how we can pull some data out of the database.

baseURI="http://localhost:3000/?user=admin&pass[$regex]=^"
chars=list(string.ascii_lowercase + string.ascii_uppercase + string.digits)
count=0

while (not found):
   currentCharacter=chars[count]
   url=baseURI + foundString + currentCharacter + ""

   if requests.get(url).text == "Success":
       count=0
       foundString+=currentCharacter
       url=baseURI+foundString+"$"
       found = requests.get(url).text == "Success":
   else:
       count+=1

Once we kick off the exploit, the script continuously iterates off every character.

This Python script performs a blind NoSQL injection to extract a password.

The main objective here is to extract the clear text password, since that was our vulnerable parameter in this case. This exploit is 13 lines of code that took about 10 minutes to write. With NoSQLmap, this could be even easier.

Now, I know all you Java and C# developers are out there thinking your applications are safe. You'll be surprised to know that you're still vulnerable. All it takes is a very interesting approach to query building by parsing JSON strings as queries.

In 2021, a quite popular open source chat server identified this exploit, using regex blind injection. The attackers in this case pulled out the reset tokens for users. Once they were able to reset a user’s password, they escalated the user’s privileges, making them an admin. Once an admin, they could set up integration, which is a fancy word for running code on your server. And once that happens, you've been pwned.

So it bears repeating: Never trust any input from any user, ever!

2. Social engineering attacks

People and businesses get hacked every day, and most security attacks and data breaches use social engineering. Great hackers will only let you know about their presence when they want you to know about it. This brings me to the second common misconception:

I don't need authentication because the database will always be running on a private network.

Authentication is the most basic security feature. Whether you're using SCRAM-SHA, LDAP, x509, or Kerberos, if you do not lock the front door, someone will gain access, and social engineering is the preferred method. All it takes is someone innocently clicking on a malicious file, which results in a macro trojan that gives the attacker access to the network. Once they're in your network, they can scan for open ports, then test if authentication is enabled for the database.

Network scan.

Once they find a database without authentication, you've been pwned.

You've been pwned.

It's that simple.

3. TLS and network traffic

Let's say you have now enabled authentication, your data is now behind a lock and a strong password (at least 16 characters using both uppercase and lowercase letters, numbers, and symbols). You have even moved credentials into a secrets vault to stop attackers from reading them out of the source code or config files. You're safe, right? Well, this brings me to the third common misconception:

We don't need TLS, MongoDB uses a binary protocol.

Unfortunately, with the popularity of bring-your-own-device options, employees often install software from unofficial sources without any permission or oversight from IT. Vulnerabilities in third-party software can easily lead to unauthorized access to the network by a malicious actor. Once again, they can perform a scan and check to see if authentication is set up, and it is.

Checking authentication.

At this point, they can attempt a brute force attack, but that's a lot of work, and hackers prefer easier approaches. Instead, they start sniffing the network and find multiple packets for the MongoDB database.

Sniffing the network.

They can intercept the traffic and send it to their own machine. Once they have the data on their machine, and if they know their tools well (Tshark or Wireshark would help), they can access a PCAP file. And if they output it as JSON, they can use jq to manipulate it. The example below shows BSON as hexadecimal code.

BSON dump.

The CyberChef tool has a decoder for BSON.

Decoding BSON.

No username is required. And once again, you've been pwned.

The lesson here is that TLS should always be used to ensure any data that is transferred between two systems is encrypted and, even if intercepted, cannot be decrypted without the private key.

Retrieving files after they've been deleted

So now you have authentication with strong passwords, the application is safe, the network is safe, and you’re using encryption at rest. You’re totally secure, right? Nope. This brings me to the fourth common misconception:

Encryption at rest will protect me against hackers.

A 2014 study found that 78% of drives that were sold for reuse after decommissioning and allegedly being wiped still had data on them; 23% of those still had associated social security numbers, and 21% had financial information. Needless to say, this is a problem. Hackers who use a keyfile for encryption at rest can retrieve files from an old, discarded drive or one that was not securely wiped. And once again, you've been pwned. The best defense against this sort of vulnerability is to always use a key management interoperability protocol (KMIP) server for encryption at rest.

Malicious insiders

It's important to remember that if an attacker gains entry to your system while it's running, they can get ahold of your data, no matter what system you're using. This brings me to an attack vector that is one of the biggest risks for businesses right now: malicious insiders.

According to a recent study, 70% of organizations are seeing an increase in insider attacks. It can take up to 200 days to identify these attacks. Around the globe, 35% of businesses have been affected.

Imagine a trusted employee accepts a job with one of your competitors and, in the process of accepting a position with them, decides to take your database with them. They don't want to use their credentials to access it for fear of being detected. They could dump the memory and get what's in the cache, but that's a lot of work. They could also dump the memory and look for the encryption keys, which is also a lot of work. Alternatively, they could just use the keyfile and dump the data. And once again, you've been pwned.

Running host with KMIP.

Insider attacks are some of the hardest to protect against because of the level of knowledge and access of employees. If it seems like no one is safe, that's what I'm trying to show you. If someone makes it onto your server while it's running, all bets are off, especially if they have root access. client-side field-level encryption encrypts the data on the application server before it's sent to the database — not even your DBAs can read the data. The keys that are being used are also in a key management system (KMS). Client-side field-level encryption should be used for all sensitive information.

Secure by default

Let's face it, security configuration is a full-time job, and you already have one of those. MongoDB Atlas provides a database that is secure by default. At a minimum, it always requires a username and password, it always requires you to use TLS, and there are network and IP access lists that further restrict access to the database.

MongoDB Atlas uses a zero-trust design that complies with all the major regulatory frameworks organizations are subject to. When you use client-side field-level encryption for applications outside of mongoDB Atlas and put your data inside of Atlas, which is secure by default, you've added yet another layer between malicious insiders and your data.

Try a preview version of Queryable Encryption to encrypt data end-to-end and query on randomly encrypted data. Try MongoDB Atlas for free.