Al pasar parámetros $_GET a una consulta, debemos asegurarnos de que se han convertido en strings. Un usuario puede insertar un array asociativo en una petición GET, provocando consultas $ no deseadas.
Un ejemplo aparentemente inofensivo: supongamos que estamos buscando información de un usuario con la petición http://www.example.com?username=bob. La aplicación realiza la consulta $collection->find(array("username" => $_GET['username'])).
Alguien podría alterarlo realizando una consulta a http://www.example.com?username[$ne]=foo, con lo que PHP lo convertirá automáticamente a un array asociativo, creando la consulta $collection->find(array("username" => array('$ne' => "foo"))), que devolverá todos los usuarios con nombre distinto de "foo" (probablemente, todos).
Es sencillo defenderse de un ataque como éste: hay que asegurarse de que los parámetros $_GET son del tipo esperado antes de enviarlos a la base de datos (en este caso, convertirlos a string).
Tenga en cuenta que este tipo de ataque se puede usar con cualquier interacción con una base de datos que localice documentos, incluyendo actualizaciones, busquedas con modificación, y eliminaciones.
Gracias a » Phil por apuntar esto.
Para más información sobre ataques tipo inyección SQL con MongoDB revise » la documentación principal.
Si se está usando JavaScript, debemos asegurarnos que cualquier variable que cruce los límites PHP-JavaScript se pasa en el campo scope de MongoCode, y no interpolado en el código JavaScript. Esto sucede al llamar a MongoDB::execute(), consultas $where, MapReduces, agrupaciones, y cualquier otra situación en que se proporcione código JavaScript a la base de datos.
Nota:
MapReduce ignora el campo scope de MongoCode, pero hay una opción scope disponible en el comando que puede utilizarse en su lugar.
Por ejemplo, supongamos que tenemos un código JavaScript para saludar a los usuarios en los registros de la base de datos. Podríamos:
<?php
// ¡no haga esto!
$username = $_POST['username'];
$db->execute("print('Hola, $username!');");
?>
Pero, ¿qué ocurriría si un usuario malicioso metiera código JavaScript?
<?php
// ¡no haga esto!
// $username tiene como valor "'); db.users.drop(); print('"
$db->execute("print('Hola, $username!');");
?>
Ahora MongoDB ejecuta el código JavaScript "print('Hola, '); db.users.drop(); print('!');". Este ataque es fácil de evitar: utilice scope al pasar variables de PHP a Javascript:
<?php
$scope = array("user" => $username);
$db->execute(new MongoCode("print('Hello, '+user+'!');", $scope));
?>
Esto añade la variable user al ámbito de JavaScript. Si ahora alguien quisiera añadir código malicioso, MongoDB imprimiría, sin causar daños, Hello, '); db.dropDatabase(); print('!.
El uso de scope ayuda a prevenir que se ejecutene en la base de datos entradas maliciosas. Sin embargo, debe asegurarse de que su código no cambie y ejecute los datos de entrada. Por ejemplo, nunca utilice la función eval de JavaScript con los datos de entrada de un usuario:
<?php // ¡no haga esto! // $jsShellInput es "db.users.drop();" $scope = array("input" => $jsShellInput); $db->execute(new MongoCode("eval(input);", $scope)); ?>
Use siempre scope y nunca permita que la base de datos ejecute como código los datos de entrada del usuario.