One-step to prevent potential NoSQL Injection in your mongodb application
Tags: node, mongodb, security, middleware
Published: 2020-04-26 19:30:26

It starts with "Once Upon a Time" when I was learning MongoDB and thought that with the schemaless feature, it could be more secure than SQL Databases (SQL Injections). So I migrated all my projects to MongoDB. 

Now, for the past few months, I have been working on NoSQL Injection and planning to start a series of tutorials on it. 

## What is Injection
An injection is a security vulnerability that lets attackers take control of database queries through the unsafe use of user input. It can be used by an attacker to: Expose unauthorized information. Modify data.


Let me show you a glimpse of NoSQL Injection at first.

Suppose, your application is accepting JSON `username` and `password`, so it can be bypassed by
```json
{
    "username": { "$ne": "malicious@example.com" },
    "password": { "$ne": "mymaliciouspassword" }
}
```

Now if at backend you are using
```js
Model.findOne(req.body)

// or

Model.findOne({ username: req.body.username, password: req.body.password });
```
your application is vulnerable to NoSQL Injection. How? Let's substitute those values


```js
Model
  .findOne({ 
    username: { 
      $ne: "malicious@example.com" 
    },
    password: {
      $ne: "mymaliciouspassword"
    }  
})
```

Now, if there is at least one document in the collection and not having the same username and password as the attacker has passed, it can log in to your web application with the very first document that matches this criterion

Practical Example: https://mongoplayground.net/p/omLJSlWfR-w

## Preventing NoSQL
There is only one thing you can do, "SANITIZATION" by casting the input to in specific type. Like in this case, casting username and password to `String()` would work

As you know `String()` on any object would be `[object Object]` so I am directly substituting the value here
```
Model.findOne({
  username: "[object Object]",
  password: "[object Object]"
})
```

In production, this would be the rarest document in the collection.

Practical Demonstration: https://mongoplayground.net/p/XZKEXaypJjQ


### ExpressJS middle-ware approach
Four months ago I had created a question StackOverflow (https://stackoverflow.com/questions/59394484/expressjs-set-the-depth-of-json-parsing), to which a user named [x00](https://stackoverflow.com/users/12610347/x00) posted the answer about the solution of setting up the depth of parsing nested JSON body.

Practical Demonstration

```js
...
const depth_limit = 2; // the depth of JSON to parse

app.use(express.json())
const get_depth = (obj) => {
    let depth = 0
    for (const key in obj) {
        if (obj[key] instanceof Object) {
            depth = Math.max(get_depth(obj[key]), depth)
        }
    }
    return depth + 1
}

const limit_depth = function(req, res, next) {
    if (get_depth(req.body) > depth_limit) throw new Error("Possible NoSQL Injection")
    next()
}

app.use(limit_depth)
...
```

Or if you want to use `[object Object]` notation to prevent application crash. I personally recommend you to use this one

```js
...
let depth_limit = 1; // the depth of JSON to parse

app.use(express.json())
let limit_depth = (obj, current_depth, limit) => {
    // traversing each key and then checking the depth
    for (const key in obj) {
        if (obj[key] instanceof Object) {
            if (current_depth + 1 === limit) {
                obj[key] = "[object Object]" // or something similar
            } else limit_depth(obj[key], current_depth + 1, limit)
        }
    }
}

// middle-ware in action
app.use(function(req, res, next) {
    limit_depth(req.body, 0, depth_limit);
    next()
})
...
```

**Middle-ware in action**
![](https://i.ibb.co/dgwHS04/image.png)

Practical Demonstration: https://repl.it/@tbhaxor/Preventing-NoSQL-Injection-in-Express

If you have some other cool ideas, I would love to hear from you. You can either comment down here or contact me at the following

+ [Twitter](https://twitter.com/tbhaxor)
+ [Instagram](https://instagram.com/_tbhaxor_)
+ [LinkedIn](https://linkedin.com/in/gurkirat--singh)
+ [Email](mailto:tbhaxor@gmail.com)

## References
+ [Introduction to NoSQL Injection](https://owasp.org/www-pdf-archive/GOD16-NOSQL.pdf)
+ [NoSQL Injection Payloads](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/NoSQL%20Injection)
+ [NoSQLMap - Automated NoSQL database enumeration and web application exploitation tool. ](https://github.com/codingo/NoSQLMap)
+ [NoSQLi Lab](https://github.com/digininja/nosqlilab)
+ [MongoSecure: An ExpressJS Middleware to Filter Out Malicious Payloads](https://mongo-secure.tbhaxor.com/)

Image has been taken from https://blog.sqreen.com