Al pasar parámetros $_GET
(o $_POST
)
a una consulta, se ha de asegurar de que están convertidos a string.
Un usuario puede insertar un array asociativo en peticiones GET y POST, lo que
provocaría 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 y $_POST son del tipo demandado antes de enviarlos a la base de datos (en este caso, se han de convertir 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ónscope
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.