脚本注入攻击

如果您使用的是 JavaScript,请确保任何跨越 PHP 到 JavaScript 边界的变量都通过 scope 字段传递给 MongoDB\BSON\Javascript,而不是插值到 JavaScript 字符串中。当在查询、mapReduce 和 group 命令中使用 $where 子句时,以及在您将 JavaScript 传递到数据库的任何其他时候,都会出现这种情况。

例如,假设我们在数据库日志中有一些 JavaScript 用于问候用户。我们可以这样做

<?php
$m
= new MongoDB\Driver\Manager;

// 不要这样做!!!
$username = $_GET['field'];

$cmd = new \MongoDB\Driver\Command( [
'eval' => "print('Hello, $username!');"
] );

$r = $m->executeCommand( 'dramio', $cmd );
?>

但是,如果恶意用户传递一些 JavaScript 怎么办?

<?php
$m
= new MongoDB\Driver\Manager;

// 不要这样做!!!
$username = $_GET['field'];
// $username 被设置为 "'); db.users.drop(); print('"

$cmd = new \MongoDB\Driver\Command( [
'eval' => "print('Hello, $username!');"
] );

$r = $m->executeCommand( 'dramio', $cmd );
?>

现在 MongoDB 执行 JavaScript 字符串 "print('Hello, '); db.users.drop(); print('!');"。这种攻击很容易避免:使用 args 将变量从 PHP 传递到 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 );
?>

这为 JavaScript 范围添加了一个参数,该参数用作 greet 函数的参数。现在,如果有人试图发送恶意代码,MongoDB 将无害地打印 Hello, '); db.dropDatabase(); print('!

使用参数有助于防止恶意输入被数据库执行。但是,您必须确保您的代码不会转过来再次执行输入!最好从一开始就避免在服务器上执行任何 JavaScript。

强烈建议您远离使用查询的 » $where 子句,因为它会严重影响性能。如果可能,请使用正常的查询运算符或 » 聚合框架

作为 » MapReduce 的替代方案,它使用 JavaScript,请考虑使用 » 聚合框架。与 Map/Reduce 不同,它使用一种惯用语言来构建查询,而无需编写和使用 Map/Reduce 所需的较慢的 JavaScript 方法。

从 MongoDB 3.0 开始,» eval 命令 已被弃用,也应避免使用。

添加注释

用户贡献的注释 1 条注释

Robin
7 年前
第二个示例不应该有这个吗

$_GET['field'] = "'); db.users.drop(); print('";

在它设置 $username 之前?
To Top