Kavi Siegel
Kavi Siegel

Reputation: 2994

Sandboxing Mongo->execute(MongoCode) in PHP to prevent any DB interaction

As a feature in the software I'm writing, I'm allowing myself to create calculators written in JS to compute the fees to be applied to a specific set of data, using said data as a reference. Since I'm using Mongo, I can run this safely server-side, and the browser can just call a php page and get the response. The function will be written from an administration control panel and saved to the database. I of course won't be doing any db interactions from inside that function, but executing mongocode is done within the database, so mongocode by nature can do db.foo

Just to protect myself and anyone else who might end up writing calculators, I've set db = null; in $context being passed to new MongoCode()

It looks a bit like this:

$sample = [
    'estimatedvalue' => 200,
    'estimatedcost' => 400,
    'contractor'    => false,
    'db'    => null,
];
$fees = [
    '_id'   => new MongoId(),
    'name'  => 'Friendly name!',
    'code'  => new MongoCode('function(){return (contractor ? estimatedCost : estimatedValue)*0.01; /* If a contractor is doing the work, base fee on cost. */}', $sample),
];

$a = $this->siteDB->execute($fees['code']);

if(isset($a['errno'])){
    echo $a['errmsg'];
}else{
    var_dump($a['retval']);
}

Fortunately, that works, and if I was to inject that into all context, there would be no db. commands runnable. I don't want to create a point where NoSQL injection can happen!

An example of something that this prevents is:

 'code' => new MongoCode('function(){db.foo.remove();}', $sample),
 // Since db is now null, the above won't work

My concern: Are there any other variables that exist in this MongoCode Execute environment that could be potentially harmful to leave in a user-editable function? I couldn't find any documentation on what else is accessible through mongocode functions. If db is it, then I'm all set!

Upvotes: 1

Views: 751

Answers (1)

kris
kris

Reputation: 23592

This is not safe, and I don't think you can have a user-editable JS function that is. For example, this requires no variables and shuts down your server:

> db.eval("(new Mongo('localhost:27017')).getDB('admin').shutdownServer()")

They can insert data, drop databases, connect to other servers in your system, and generally wreck havoc.

If you are trying to allow a user-editable compute function in JavaScript, use a separate JS engine, pull the values from MongoDB, and pass the values + user-defined function to the totally separate JS engine.

Upvotes: 1

Related Questions