comments (not for humans)
My previous post explained how NOSQL-injection can occur when using NOSQL-databases. I showed an example using MongoDB. In this post I'll show you how to protect your application.

Secure APIs

The most important practice is to as much as possible stick to APIs that don't involve string concatenation. Many of the database drivers seem to include fluent APIs where query language is reflected in the programming language. The .NET implementation called mongodb-net, has a syntax like this: coll.FindOne(Where.Field(a => a == 1)); This allows you to develop without thinking about how the query is actually constructed. The escaping is (hopefully) performed by the framework.

Mathias Stearn also mentioned this API for building safe queries:queryObj.append("b", 2)

Insecure APIs

When using the insecure APIs like:db.myCollection.find("{ $where: 'this.a > " + userinput + "' }");"{ $or : [ { a : 1 } , { b : " + userinput + " } ] }")make sure you pay close attention. Whenever you do string concatenation, you need to escape the data correctly. MongoDB supports converting javascript queries to it's native query language expressed in BSON. When using this, there are two contexts you need to be aware of:

  1. Inside a javascript string
  2. Elsewhere
Whenever you are concatenating data within a javascript string, make sure you do javascript escaping using a library like the OWASP ESAPI encoder or the AntiXss library from Microsoft's Web Protection Library.

If you are concatenating user input outside a string, you really need to be careful. It's really hard to get the escaping right unless the datatype of the variable is an integer or similar where the possible values are known and limited.

Update 2010-08-02: If you are using MongoDB from PHP, you might want to look at blog post from Phil

Even when using the secure API under PHP mongo is still very vulnerable to No-SQL injection (see The only sure fire way to prevent this is to cast all your inputs to their appropriate data types and prevent JSON from being inputted
@Phil: Thanks! Interesting stuff! I can imagine the same problem existing for other languages as well, especially combined with something like HTTP parameter pollution (which in some languages result in arrays or similar)
good point that it depends on the driver

those who have a need can use --noscripting to avoid $where case

you've probably seen this but for everyone else:
For most languages, a special MongoDB "code" type is available that has scope component. You can use the scope to make passing user input safer:

{$where : new CodeWScope("this.a < max", {max : userinput})}

(Made-up language, since the shell doesn't support code with scopes.)

Also, the PHP vulnerability is documented in the manual:
Comments closed for this post