Si se utiliza JavaScript, asegúrese de que todas las variables que
atraviesan la frontera PHP-JavaScript se pasen en el campo
scope
de MongoDB\BSON\Javascript,
y no se interpolen en la string JavaScript. Esto puede ocurrir cuando
se utilizan cláusulas $where
en las consultas, los
comandos mapReduce y group, y en cualquier otro momento en que se pueda pasar
JavaScript a la base de datos.
Por ejemplo, supongamos que tenemos un JavaScript para saludar a un usuario en los logs de la base de datos. Podríamos hacer:
<?php
$m = new MongoDB\Driver\Manager;
// No haga esto !!!
$username = $_GET['field'];
$cmd = new \MongoDB\Driver\Command( [
'eval' => "print('Hello, $username!');"
] );
$r = $m->executeCommand( 'dramio', $cmd );
?>
Sin embargo, ¿qué pasa si un usuario malintencionado pasa JavaScript?
<?php
$m = new MongoDB\Driver\Manager;
// No haga esto !!!
$username = $_GET['field'];
// $username equivale a "'); db.users.drop(); print('"
$cmd = new \MongoDB\Driver\Command( [
'eval' => "print('Hello, $username!');"
] );
$r = $m->executeCommand( 'dramio', $cmd );
?>
Ahora MongoDB ejecuta la string JavaScript
"print('Hello, '); db.users.drop(); print('!');"
.
Este ataque es fácil de evitar: utilice args
para pasar
variables de PHP a JavaScript:
<?php
$m = new MongoDB\Driver\Manager;
$_GET['field'] = 'derick';
$args = [ $_GET['field'] ];
$cmd = new \MongoDB\Driver\Command( [
'eval' => "function greet(username) { print('Hello, ' + username + '!'); }",
'args' => $args,
] );
$r = $m->executeCommand( 'dramio', $cmd );
?>
Esto añade un argumento al ámbito JavaScript, que se utiliza como argumento
para la función greet
. Ahora si
alguien intenta enviar código malintencionado, MongoDB imprimirá inofensivamente
Hello, '); db.dropDatabase(); print('!
.
Utilizar argumentos ayuda a prevenir la ejecución de entradas malintencionadas por la base de datos. Sin embargo, se debe asegurar de que el código no devuelva ni ejecute la entrada de ninguna manera. Es preferible evitar ejecutar cualquier JavaScript en el servidor en primer lugar.
Se recomienda mantenerse alejado de la cláusula » $where en las consultas, ya que afecta significativamente el rendimiento. En la medida de lo posible, utilice operadores de consulta normales o el » Framework de agregación.
Una alternativa a » MapReduce, que utiliza JavaScript, es el » Framework de agregación. A diferencia de Map/Reduce, utiliza un lenguaje idiomático para construir consultas, sin tener que escribir y utilizar el enfoque JavaScript más lento que Map/Reduce requiere.
La » comando eval ha sido deprecado desde MongoDB 3.0, y también debe ser evitado.