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'] ));