Is nosql injection possible for Ruby on Rails with Mongoid?

818 Views Asked by At

I'm trying to investigate if nosql injection is possible on Ruby on Rails with mongo and mongoid gems.

I did Mongodb's requests using Mongo::Client collections and models with Mongoid::Document inclusion.

I tried to pass some command characters like ' " \ ; { }, but is was sanitaized. Passing GET search?title[$ne]=foo was traited like {"title"=>"{\"$ne\"=>\"foo\"}"}, so it don't seems like any problem here.

Is any nosql injection possible if I use ordinary methods of this technology stack?

3

There are 3 best solutions below

0
On BEST ANSWER

Common operations including queries and inserts/updates in Mongoid sanitize their inputs, thus most times one does not need to worry about "nosql injection".

However, there are methods that pass commands directly to the database, and in those cases it is important to carefully consider whether unsanitized user input can end up as a database command. For example, if Post is a Mongoid model, one can run the following command to create an infinite loop in a MongoDB server:

Post.all.map_reduce('function(){while(true);}','function(){}').out(inline:1).count

Another example is Database#command method provided by the driver to run arbitrary database commands: http://api.mongodb.com/ruby/current/Mongo/Database.html#command-instance_method. If an application places user input into parameters given to this method, this creates potential for "nosql injection".

Note also that it is not necessary to pass an unexpected command to the database - sometimes unexpected data is sufficient. See, for example, https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS. Assuming the Post model has a body field, passing an arbitrary regular expression from the user could be problematic:

# This might take a while
Post.where('body' => {'$regex' => '((a|a?|a*)*)*$'}).count
0
On

Possible, and easily overlooked.

In fact, you are pretty close.
Untrust sources are not just from GET parameters.
Mongoid won't help you with anything; in your example, what prevents the succeeded exploitation is the fact that, in RoR, you can't pass a Hash as a GET parameter.

An unsanitized parameter can come from JSON, like this one for example.

posts = PrivatePost.where({ owner_id: json_params[:owner_id] }).each.to_a

Where json_params[:owner_id] could contains { '$ne': 'the owner' },
which can leak posts to someone else.

Or mess with the operation scope via POST-based API:

Post.where({ _id: json_params[:id] }).delete_all
0
On

This is from the mongdodb docs

As a client program assembles a query in MongoDB, it builds a BSON object, not a string. Thus traditional SQL injection attacks are not a problem. More details and some nuances are covered below.

MongoDB represents queries as BSON objects. Typically client libraries provide a convenient, injection free, process to build these objects. Consider the following C++ example:

https://docs.mongodb.com/manual/faq/fundamentals/#how-does-mongodb-address-sql-or-query-injection