Mongodb is vulnerable to SQL injection in PHP at least

Published on by

Its a common misconception that as MongoDB does not use SQL it is not vulnerable to SQL injection attacks. PHP uses objects rather than SQL to pass queries to the MongoDB server; for example the following script selects an item form MongoDB where the username equals 'bob' and the password equals 'password'.

$collection->find(array(
    "username" => $_GET['username'],
    "passwd" => $_GET['passwd']
));

This is equivalent to the SQL syntax

mysql_query("SELECT * FROM collection
    WHERE username=" . $_GET['username'] . ",
    AND passwd=" . $_GET['passwd'])

In a normal SQL injection attack we can replace either of the two input parameters with a string such that the SQL query always returns true. e.g.

login.php?username=admin&passwd=" OR 1 --

That wont work with MongoDB; however if we can pass in an object to the PHP MongoDB driver we could alter the query in a similar fashion. Luckily PHP provides us with a way to pass objects as GET or POST parameters:

login.php?username=admin&passwd[$ne]=1

This creates the MongoDB query

$collection->find(array(
    "username" => "admin",
    "passwd" => array("$ne" => 1)
));

Which is the equivalent to the following SQL statement which, unless the password is "1" will always return true.

mysql_query("SELECT * FROM collection
    WHERE username="admin",
    AND passwd!=1

The solution is to ensure your variables are properly typed before they are passed into the MongoDB driver. The following code is not vulnerable to MongoDB injection:

$collection->find(array(
    "username" => (string)$_GET['username'],
    "passwd" => (string)$_GET['passwd']
));