MongoDB 보안 스크립트 주입 공격

JavaScript를 사용하는 경우 PHP에서 JavaScript로의 경계를 넘는 모든 변수가 JavaScript 문자열에 삽입되지 않고 MongoDB\BSON\Javascriptscope 필드에 전달되는지 확인하십시오. 이는 쿼리, mapReduce 및 그룹 명령에서 $where 절을 사용할 때 발생할 수 있으며 JavaScript를 데이터베이스에 전달할 수 있는 다른 모든 경우에 발생할 수 있습니다.

예를 들어 데이터베이스 로그에 사용자를 맞이하는 JavaScript가 있다고 가정합니다. 우리는 할 수 있습니다:

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

// Don't do this!!!
$username = $_GET['field'];

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

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

그러나 악의적인 사용자가 일부 JavaScript를 전달하면 어떻게 될까요?

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

// Don't do this!!!
$username = $_GET['field'];
// $username is set to "'); 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 );
?>
                  
                

이것은 greet 함수에 대한 인수로 사용되는 JavaScript 범위에 인수를 추가합니다. 이제 누군가가 악성 코드를 보내려고 하면 MongoDB는 무해하게 Hello, '); db.dropDatabase(); print('!.

인수를 사용하면 악의적인 입력이 데이터베이스에서 실행되는 것을 방지할 수 있습니다. 그러나 코드가 돌아가지 않고 어쨌든 입력을 실행하는지 확인해야 합니다! 처음부터 서버에서 JavaScript를 실행하지 않는 것이 가장 좋습니다.

쿼리와 함께 » $where clause은 성능에 상당한 영향을 미치므로 사용하지 않는 것이 좋습니다. 가능한 경우 일반 쿼리 연산자 또는 » Aggregation Framework를 사용하세요.

자바스크립트를 사용하는 » MapReduce의 대안으로 » Aggregation Framework를 사용하는 것이 좋습니다. Map/Reduce와 달리 Map/Reduce에 필요한 느린 JavaScript 접근 방식을 작성하고 사용할 필요 없이 관용적 언어를 사용하여 쿼리를 구성합니다.

» eval command는 MongoDB 3.0부터 더 이상 사용되지 않으며 피해야 합니다.