이 페이지에서는 MongoDB 클라이언트 라이브러리를 사용할 때 애플리케이션 개발을 위한 권장사항을 설명합니다. 애플리케이션이 신뢰할 수 없는 입력을 처리할 때 발생할 수 있는 인젝션 공격 및 기타 보안 문제의 위험을 줄이기 위해 다음 권장 사항을 따르세요.
SRV 연결 문자열 사용
배포서버에서 지원하는 경우, 표준 mongodb:// 형식 대신에 mongodb+srv:// 연결 문자열 형식을 사용하세요. +srv 형식은 연결을 위해 자동으로 전송 계층 보안(TLS)을 활성화하여, 기본값으로 애플리케이션과 MongoDB 배포서버 간의 트래픽을 암호화합니다. 표준 형식은 명시적으로 설정하지 않으면 TLS를 활성화하지 않습니다.
+srv 형식은 DNS SRV 기록에서 전체 시드 호스트 목록을 확인합니다. 기본 호스트가 변경되어도 연결 문자열을 업데이트할 필요가 없습니다.
경고
드라이버는 원래 시드 호스트 이름과 동일한 상위 도메인을 공유하는 SRV 조회 결과를 신뢰합니다. 예시로 foo.example.com에 대한 조회는 node1.foo.example.com을(를) 반환할 수 있습니다. 또한 foo.example.com 아래에 있지 않더라도 example.com 상위 도메인을 공유하는 node1.example.com을(를) 반환할 수도 있습니다.
악의적이거나 손상된 DNS 서버는 연결 설정 중에 애플리케이션을 공격자가 제어하는 호스팅하다로 리디렉션하려고 시도할 수 있습니다. 상위 도메인 제한으로 이러한 위험을 제한합니다. 시드 호스팅하다 이름의 부모 도메인이 클러스터의 호스팅하다로만 해결되는지, 또는 동일한 신뢰할 수 있는 개체가 제어하는 클러스터로 해결되는지 확인합니다.
JSON을 BSON으로 변환하기 전에 신뢰할 수 없는 입력을 검증하세요
많은 클라이언트 라이브러리는 JSON string을 BSON 문서로 변환하는 편의 메서드를 제공합니다. (예시: Extended JSON을 통해서) 애플리케이션이 결과 문서를 유효성 검사 없이 쿼리, 업데이트 또는 명령으로 전달핕는 경우, 공격자가 해당 작업의 의미를 변경할 수 있습니다.
JSON 요청 본문을 허용하고 string 값을 포함하는 name 필드를 예상하는 API 엔드포인트를 고려해 보세요. 엔드포인트가 요청 보디를 BSON으로 변환하고 그 결과를 쿼리 필터에 유효성 검사 없이 사용하는 경우를 가정합니다. 공격자는 다음 예시에서 볼 수 있듯이 예상되는 string 대신에 객체를 제출할 수 있습니다.
{"name": {"$ne": null}}
MongoDB는 $ne 필드를 리터럴 값이 아닌 쿼리 연산자로 평가합니다. 이 필터는 이름으로 단일 문서를 일치시키는 대신 name 필드가 null이 아닌 모든 문서를 일치시켜 의도한 것보다 더 많은 데이터를 노출합니다.
BSON으로 변환하기 전에 신뢰할 수 없는 입력을 JSON string으로 연결하는 것도 동일한 위험을 초래합니다. 다음 C++ 예시는 string 연결을 사용하여 사용자가 제공한 값을 JSON string에 삽입하여 쿼리 필터를 빌드합니다:
std::string json_query = "{ \"name\": \"" + user_supplied_name + "\" }"; bsoncxx::document::value filter = bsoncxx::from_json(json_query); mongocxx::cursor cursor = collection.find(filter.view());
user_supplied_name에 double quote 또는 JSON 연산자가 포함된 경우, 결과 string이 의도한 필드 값을 탈출하여 임의의 쿼리 구문을 삽입할 수 있습니다.
이 위험은 JSON string이 사용자, API 요청 또는 애플리케이션이 제어하지 않는 다른 소스에서 시작될 때마다 적용됩니다. 이러한 위험을 줄이기 위해, BSON으로 변환하기 전에 신뢰할 수 없는 입력을 형식 검사 및 유효성 검증해야 합니다. 많은 드라이버가 쿼리를 빌드하는 데 사용할 수 있는 타입이 지정된 문서 API 또는 쿼리 빌더를 제공합니다. 또한 변환을 위해 JSON 입력을 수락하기 전에 애플리케이션 내에서 JSON schema 또는 유사한 유효성 검사 계층을 적용할 수 있습니다.
다음 예시에서는 이전 연결 예시와 동일한 필터를 빌드하지만, 대신 형식화된 문서 빌더를 사용합니다:
bsoncxx::builder::basic::document filter_builder; filter_builder.append( bsoncxx::builder::basic::kvp("name", user_supplied_name)); mongocxx::cursor cursor = collection.find(filter_builder.view());
빌더는 user_supplied_name을(를) 구문 분석할 문자열의 일부가 아닌 값으로 처리하므로, 이 값은 쿼리의 구조를 변경할 수 없습니다.
쿼리를 문자열 대신 BSON 문서로 빌드하면 공격자가 조작할 쿼리 문자열이 없으므로 기존 SQL 주입을 방지할 수 있습니다. 자세한 내용을 학습하려면 MongoDB Server 매뉴얼에서 FAQ: MongoDB 기본 사항 을 참조하세요. 확장 JSON 유형 및 변환에 대해 자세히 학습하려면 MongoDB Server 매뉴얼에서 MongoDB 확장 JSON 을 참조하세요.
서버 측 JavaScript 실행 제한
MongoDB는 $where, $function, $accumulator 및 mapReduce 등 JavaScript를 실행하는 연산자 및 명령을 지원합니다. 애플리케이션이 사용자 입력으로부터 이러한 표현식 중 하나를 빌드하면, 서버는 해당 입력을 코드로 실행합니다. 이러한 동작은 애플리케이션 코드에서 신뢰할 수 없는 입력을 eval 함수에 전달하는 것과 동일한 클래스의 위험을 야기합니다.
이 위험을 줄이려면 다음 권장 사항을 따르십시오.
string 연결을 피하세요: JavaScript string에 신뢰할 수 없는 입력을 연결하거나 삽입하여
$where표현식,$function본문 또는$accumulator함수를 빌드 마세요. 대신 표준 쿼리 연산자를 사용하십시오. MongoDB는 JavaScript를 실행하지 않고도 이를 평가하기 때문입니다.서버 측 스크립트 비활성화: 애플리케이션에서
$where,$function,$accumulator또는mapReduce을(를) 사용하지 않는 경우 서버 측 스크립트를 비활성화합니다.security.javascriptEnabled구성 옵션을false(으)로 설정하거나mongod또는mongos프로세스를 시작하고--noscripting옵션을 전달합니다.
서버 측 JavaScript 실행 보안에 대해 자세히 알아보려면 보안 구성 옵션으로 MongoDB 실행을 참조하세요.
$where 연산자에 대해 자세히 학습하려면 MongoDB Server 매뉴얼에서 $where 를 참조하세요.
추가 정보
자체 관리형 배포서버 보안에 대한 권장사항 목록은 MongoDB Server 매뉴얼의 보안 체크리스트를 참조하세요.