Skip to content

NoSQL Injection

What does this mean ?

NoSQL injection is a security flaw in a NoSQL database-powered web application. A NoSQL injection, like a SQL injection, can allow attackers to circumvent authentication, exfiltrate sensitive data, tamper with database data, or potentially compromise the database and the underlying server. The majority of NoSQL injection vulnerabilities arise as a result of developers accepting and processing user inputs without adequately sanitizing them.

What can happen ?

When a query, most usually supplied by an end-user, is not sanitized, the attacker is able to incorporate malicious input that runs an undesirable command on the database. This enables attackers to takeover servers and exploit vulnerabilities that extend beyond the traditional scope of SQL injection attacks, making NoSQL injections more serious than SQL injection in some circumstances.

Recommendation

  • Always validate, and filter to match the allowed and expected data.
  • Familiarize yourself with standard SQL approaches, and use prepared statements to safeguard the data provided to the queries.
  • To process user input, avoid using vulnerable JavaScript functions such as eval(), setTimeout(), setInterval(), and Function ()
  • NoSQL database security rules and instructions must be carefully and properly studied.

Sample Code

Vulnerable :

public List<Item> Get(string name) {
    var filter = "{$where: \"function(){return this.name == '" + name + "'}\"}";
    return items.Find(filter).ToList();
}

Non Vulnerable :

public List<Item> Get(string name) {
    return items.Find(item => item.name == name).ToList();
}  

Vulnerable :

app.post('/documents/find', (req, res) => {
    const query = {};
    if (req.body.type === "secret projects") { // hide my secret projects
        return res.json([]);
    }
    if (req.body.title) {
        query.title = req.body.title;
    }
    if (req.body.type) {
        query.type = req.body.type;
    }
    if (!query.title && !query.type) {
        return res.json([]);
    }
    Document.find(query).exec()
        .then((r) => res.json(r))
        .catch((err) => res.json(err));
});

Non Vulnerable :

const validate = function (req, res, next) {
    const body = req.body;
    If (body.title && typeof body.title !== string) {
        return next(new Error(title must be a string));
    }
    If (body.type && typeof body.type !== string) {
        return next(new Error(type must be a string));
    }
    next();
}

References