

MongoDB remote command execution vulnerability: nightmare or eye opener? - ehsanf
http://blog.sdelements.com/mongodb-remote-command-execution-vulnerability-nightmare-or-eye-opener

======
sehrope
Having your DB server (regardless of type) exposed to the entire internet is a
bad idea but that's not the real problem here (it just makes this _really_
scary for people running wide open MongoDB instances). This is a lack of
validation of client inputs by the server itself and (in my opinion) a
dangerous default choice of trusting your client.

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...](http://www.postgresql.org/docs/9.1/static/plperl-trusted.html)

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...](http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:16212348050)

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.

------
optymizer
This relies on javascript to be passed to $where. There is no excuse for not
sanitizing your inputs.

~~~
ajross
The same thing could be said of SQL injection attacks, yet...

~~~
optymizer
... no one is pointing fingers at MySQL, like they are at MongoDB, as if this
is some kind of security flaw in MongoDB.

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.

------
abentspoon
Thanks to $elemMatch and automatic parameter parsing, this vulnerability is
easier to exploit than it would seem.

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

~~~
cheald
Per usual, even if you're using something that isn't Mongo, it's good practice
to explicitly cast your untrusted params before passing them to a query.

    
    
        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...](https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-
security/t1WFuuQyavI)

------
wheaties
As a developer that uses MongoDB in production I am shocked! Shocked, I tell
you.

~~~
yet
And why are you shocked? Because you don't know what you are doing?

~~~
tjtrapp
Totally unnecessary comment. I would down vote you if I could.

------
nickporter
I guess this is only a real problem if you're exposing your MongoDB instance
to the internet.

~~~
achillean
By default, I believe MongoDB listens on 0.0.0.0 which means that servers
unprotected from a firewall will expose their MongoDB database to the
Internet. Shodan confirms that there are at least 31,000 public instances of
MongoDB on the Internet at the moment (source:
<http://www.shodanhq.com/search?q=port%3A28017>).

~~~
rambot
It sounds like they listen on localhost by default
(<http://docs.mongodb.org/manual/reference/mongod/#options>), though i'm not
sure if that's always been the case. It's also possible installers change the
default behaviour. (i.e. when you install via apt, yum, homebrew, etc.)

~~~
achillean
Good point, it might have changed recently and last I installed it on Ubuntu
it listened on 0.0.0.0. It certainly would make a lot more sense to listen to
localhost by default, which is what most daemons do.

------
cheald
This seems like Seriously Bad News for folks like MongoHQ. I'm hoping they're
running 2.4.1, though?

~~~
mrkurt
It's less of a problem than you'd expect, most of our DBs run in isolated
processes and an authenticated user (even with shell) can't really break out
and run wild on the environment. We expected that the Mongo javascript engine
would have vulnerabilities like this and started trying to get ahead of them
about 18 months ago.

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.

~~~
cheald
That's great to hear. Big respect to you guys for solving that problem before
it was a problem!

------
shin_lao
Doesn't the MongoDB daemon run in a privilege-free sandboxed environment?

~~~
mrkurt
Depends who's running it. :)

