如果您正在使用 JavaScript,請確保任何跨越 PHP 到 JavaScript 邊界的變數,都是在 scope
欄位中傳遞,而不是內插到 JavaScript 字串中, MongoDB\BSON\Javascript。當您在查詢中使用 $where
子句、mapReduce 和 group 指令,以及任何其他可能將 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 子句,因為它會顯著影響效能。在可能的情況下,請使用正常的查詢運算符,或 » 聚合框架。
作為使用 JavaScript 的 » MapReduce 的替代方案,請考慮使用 » 聚合框架。與 Map/Reduce 不同,它使用慣用的語言來構造查詢,而無需編寫和使用 Map/Reduce 需要的較慢的 JavaScript 方法。
自 MongoDB 3.0 起,» eval 指令已被棄用,也應避免使用。