Computer >> 컴퓨터 >  >> 프로그래밍 >> 데이터베이스

MongoDB NoSQL 인젝션(Code Injection): 위험성과 예방 방법 총정리

2019년 3월 5일 처음 게시된 글입니다.

애플리케이션 개발자, 데이터베이스 관리자(DBA), 그리고 모든 분야의 기술 종사자라면 코드 주입(code injection)은 반드시 주시해야 할 보안 위협입니다.

MongoDB NoSQL 인젝션(Code Injection): 위험성과 예방 방법 총정리

클라우드 환경은 안전하게 구축했고, 데이터베이스 접근 권한도 철저히 통제했다고 가정해 봅시다. 하지만 애플리케이션 코드는 어떠한가요? NoSQLi에서 이름에 'No'가 붙어 있다고 해서 주입 공격으로부터 자유롭다는 의미는 절대 아닙니다! NoSQL 역시 다른 데이터베이스와 마찬가지로 코드 주입에 취약할 수 있습니다. 코드 주입을 방어하지 않는 것은 현관문에는 최신 보안 시스템을 설치해 놓고 뒷창문을 활짝 열어두는 것과 같습니다.

코드 주입이란 무엇인가?

코드 주입은 검증되지 않은 데이터가 취약한 프로그램에 주입(또는 추가)되어 애플리케이션 코드 형태로 실행되는 공격 기법입니다. 그 결과는 종종 치명적입니다.

SQL 인젝션(SQLi)은 가장 흔한 주입 공격 유형 중 하나로, 10년이 넘었음에도 여전히 강세를 이어가고 있습니다. 주입 문제는 데이터베이스 언어에만 국한되지 않습니다. SQL과 NoSQL을 넘어 XPath®, XML 파서, SMTP 헤더 등 다양한 환경에서도 발생할 수 있습니다. 심각성 측면에서 코드 주입은 원격 코드 실행(RCE)과 맞먹는데, 이는 침투 테스트(penetration testing)의 '게임 오버' 화면이라 불릴 만큼 치명적인 결과를 초래합니다.

애플리케이션에서 NoSQL 인젝션(NoSQLi)을 탐지하고 예방하는 것은 매우 중요합니다. 방치된 주입 경로는 사용자 데이터의 안전을 위협할 뿐만 아니라, 신뢰 상실로 이어져 사업 자체를 위태롭게 만들 수도 있습니다. 다행히 공격 메커니즘을 이해하고 나면, 서비스 내 NoSQLi 취약점을 탐지하고 예방하기 위한 구체적인 조치를 취할 수 있습니다.

간단한 NoSQLi 공격 예제

일반적으로 MongoDB®는 안전한 BSON 쿼리 생성 도구를 통해 작성된 Binary JSON(BSON) 데이터를 처리합니다. 하지만 특정 경우에는 직렬화되지 않은 JSON이나 JavaScript(JS) 표현식, 예컨대 $where 연산자도 받아들일 수 있습니다. SQL과 마찬가지로 $where 연산자는 NoSQL에서 잠재적 주입 공격에 노출되기 쉽습니다. 다만 SQL과 달리 NoSQL의 $where는 조건식을 JS로 표현합니다. 즉, SQL이 제공하는 범위에 제한되지 않고 JS의 모든 표현력을 활용해 주입 쿼리를 만들어낼 수 있다는 뜻입니다.

공개 저장소에 정리된 MongoDB 인젝션 문자열 목록을 살펴보면, SQL 및 다른 언어의 취약점과 유사한 몇 가지 일반적인 주입 전략을 확인할 수 있습니다. 예를 들어, 고전적인 1 == 1 표현식을 사용해 쿼리가 항상 참(true)을 반환하도록 강제함으로써 숨겨진(또는 관리자 수준의) 리소스와 권한을 읽어내려는 시도가 있습니다:

$Where: '1 == 1'

또 다른 코드 조각들은 sleep() 함수를 사용해 데이터베이스 응답 속도를 늦추는 블라인드 인젝션(blind injection) 전략을 흉내 냅니다. 정교하게 설계된 필터와 결합하면 이러한 부작용(side-effect)을 통해 민감한 정보를 하나씩 열거해낼 수 있습니다:

';sleep(5000); ';it=new%20Date();do{pt=new%20Date();}while(pt-it<5000);

그리고 당연히, 주입된 쿼리가 핵심 정보를 직접 매칭하고 탈취하려는 단순한 데이터 유출(data exfiltration) 공격도 존재합니다.

' && this.password.match(/.*/)//+%00

첫 번째 예제를 제외한 나머지 두 예제는 $where 연산자를 사용하지 않습니다. NoSQL 데이터베이스를 공격하는 데 JS 스타일의 편리한 표현식이 발판으로 필요하지 않다는 의미입니다.

NoSQLi 예방 방법

NoSQLi에 저항력 있는 애플리케이션 아키텍처를 구축하려면 몇 가지 일반적인 전략을 따르는 것이 좋습니다. 이는 일반적인 인젝션 방지 권고 사항과 크게 다르지 않습니다.

MongoDB / NoSQLi도 예외가 아니다

일부 사람들은 코드 주입을 SQL에만 국한된 문제로 여기고, 다른 환경에 적용되는 주입 원칙의 유효성을 과소평가합니다. 이 글을 통해 NoSQLi가 실재하는 위협임을 확신했기를 바랍니다. 이는 "MongoDB will not prevent NoSQL injections in your Node.js app"와 같은 글에서도 잘 문서화되어 있습니다.

검증되지 않은 사용자 데이터를 신뢰하지 마세요

보안 관점에서 사용자 입력은 절대 신뢰해서는 안 됩니다!

보안 분야에서는 이미 진부하게 들릴 수 있지만, 모든 입력이 악의적인 의도로 탐색될 가능성을 염두에 두어야 합니다. 앞서 살펴본 $where 예제는 $where: unvalidated_input처럼 처리하면 안 되는 이유를 명확히 보여줍니다. 필터를 사용자에게 노출한다고 생각하는 것만으로도 충분히 위험한데, 사용자가 검증되지 않은 데이터를 더 큰 쿼리에 삽입한다는 사실 자체가 베스트 프랙티스와는 거리가 멉니다.

언어 및 통합 환경의 특수성에 유의하세요

NoSQLi가 인젝션에 면역인 것은 아니며 많은 동일한 유형의 공격에 노출되지만, 그렇다고 해서 NoSQLi 고유의 공격 전략, 혹은 NoSQL DB 위에 구축된 언어나 컴포넌트에 특화된 전략이 없다는 의미는 아닙니다. 대표적인 예로, $where는 PHP 변수처럼 보이는 형식으로 작성될 수 있기 때문에 PHP 애플리케이션 기반의 NoSQL DB는 이러한 점과 $where에 악성 문자열이 주입되어 저장될 가능성까지 고려해야 합니다.

결론

다시 한번 강조하지만, NoSQLi의 'No'가 주입 불가능을 의미하지 않습니다! NoSQL은 SQL, SMTP 헤더, XML 등 다른 환경과 마찬가지로 코드 주입에 취약하며, 애플리케이션 코드가 아닌 것을 애플리케이션 코드로 취급하는 함정에서 자유롭지 못합니다.

이 글이 NoSQLi에 대한 이해와 비즈니스에 미치는 영향을 파악하는 데 도움이 되었기를 바랍니다. 이제 코드와 프로세스를 개선하여 공격 빈도와 확산 범위, 피해 규모를 줄여나갈 수 있습니다. 앱과 호스팅 환경의 보안을 위해 MongoDB 운영 관련 조언이 필요하다면, Rackspace ObjectRocket의 숙련된 DBA들이 도움을 드릴 수 있습니다.

Rackspace DBA 서비스에 대해 더 자세히 알아보세요.

피드백 탭을 사용해 의견을 남기거나 질문할 수 있습니다. 또한 영업 상담(Sales Chat) 버튼을 클릭해 지금 바로 상담을 시작할 수도 있습니다.