https://jira.mongodb.org/browse/SERVER-207
(though it seems that it wasn't fixed when this issue was closed, so probably later https://jira.mongodb.org/browse/SERVER-697)
The same goes for my use of MongoDB.
Though I am curious if anything similar exists for CouchDB, as they seem to be encouraging dangerous configurations like that.
It's a feature, not a bug. The docs make it clear that $where can run JavaScript, so if you know what you're doing, you're not going to allow JavaScript to flow through your software as if it's valid input.
About 3% of our servers are either legacy, and the isolation hasn't been tested all that well, or sandbox environments where people share a process for tiny/test DBs. We've upgraded all of those to 2.4.1.
It certainly helps limit the damage. However, unless it is chroot-ed, it will still pose a very serious risk. And even with chroot, the damage is not totally eliminated. The attacker can start leveraging local vulnerabilities.
In rails, both of these are usually considered safe:
MysqlCollection.create(:name => params[:name])
MysqlCollection.where(:name => params[:name]).all
MongoCollection.create(:name => params[:name])
MongoCollection.where(:name => params[:name]).all
However, the mongo version is vulnerable to this exploit. /create?name[0][whatever]=anything
/get?name[$elemMatch][$where]=exploitcode MongoCollection.where(:name => params[:name].to_s)
That'll result in the literal: db.collection.where({name: "{\"$elemMatch\"=>{\"$where\"=>\"exploit\"}}"})
rather than the more exploity: db.collection.where({name: {$elemMatch:{$where: "exploit"}}})
Failing to cast params to strings can result in "injection" attacks in Mongo, even outside of the context of this bug. For example: User.where(:id => params[:id])
You could pass id[$gt]=0, resulting in: User.where(:id => {:$gt => 0})
which would match all records in the database.For completeness' sake, here's a similar exploit vector in ActiveRecord: https://groups.google.com/forum/?fromgroups=#!topic/rubyonra...
Most DBs allow something similar to this though it's generally locked down by default.
For PostgreSQL you can do it via untrusted languages though by default only super users can use those: http://www.postgresql.org/docs/9.1/static/plperl-trusted.htm...
For Oracle here's a bunch of ways to accomplish the same thing though again, by default, all are blocked for non-DBA users: http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTI...
Note that there are some times when it's useful to be able to execute misc things like this. About 6 or 7 years back I wrote something on Oracle that would execute shell commands to get iostat/vmstat output and save it on regular intervals. Could have been done from outside in (data gets pushed from unix => DB) but having it initiated by the DB itself let us control when it runs based on DB actions (triggers, DBMS_JOBs, etc). To get that setup though we had to whitelist the executables we were calling as by default on Oracle everything is blocked. It's not a common thing to do and I think it's sensible that things like that should be locked down by default.