PHP Conference Japan 2024

腳本注入攻擊

如果您正在使用 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 指令已被棄用,也應避免使用。

新增註記

使用者貢獻註記

此頁面沒有使用者貢獻註記。
To Top