업데이트됨 1개월 전
포트 27017은 MongoDB의 현관문이다. 모든 쿼리, 삽입, 관리 명령이 이 단일 TCP 포트를 통해 흐른다. 수천 개의 조직이 그 문을 활짝 열어두었다—인증도 없이, 공용 인터넷에 직접 노출된 채로. 그 결과 일어난 일은 업계가 기본 설정을 바라보는 방식을 완전히 바꿔놓았다.
포트 27017에서 무엇이 실행되는가
MongoDB는 문서 데이터베이스다. 행과 테이블 대신, 마이그레이션 없이도 진화할 수 있는 유연한 JSON 형식의 문서로 데이터를 저장한다. MongoDB가 시작되면 포트 27017에 바인딩하고 연결을 기다린다. 애플리케이션은 속도에 최적화된 바이너리 와이어 프로토콜을 사용해 통신한다. Node.js 앱이든, Python 스크립트든, mongo 셸이든—모두 이 포트에 같은 언어로 말을 건다.
하나의 포트가 모든 것을 처리한다: 문서 읽기, 문서 쓰기, 인덱스 생성, 집계 실행, 관리 명령.
MongoDB 대규모 랜섬 사태
2016년 말에서 2017년 초 사이, 데이터베이스 관리자들이 출근해 보면 MongoDB 인스턴스가 텅 비어 있었다. 데이터가 있던 자리에는 단 하나의 컬렉션만 남아 있었는데, 보통 WARNING이나 PLEASE_READ 같은 이름이 붙어 있었다. 그 안에는 비트코인을 요구하는 랜섬 노트가 들어 있었다.
공격 패턴은 단순했다: 열려 있는 포트 27017을 찾아 인터넷을 스캔하고, 자격증명 없이 접속해, 데이터를 복사하고, 모든 것을 삭제한 후, 랜섬 노트를 남긴다. 이 모든 것을 오후 한나절이면 스크립트로 만들 수 있었다.
이것이 가능했던 이유는 MongoDB의 레거시 기본 설정이 말도 안 됐기 때문이다. 데이터베이스는 0.0.0.0(모든 네트워크 인터페이스)에 바인딩되었고 인증을 요구하지 않았다. 문서를 읽지 않고 MongoDB를 설치하고 시작하면, 지구상의 누구든 완전한 관리자 권한으로 접근할 수 있는 데이터베이스를 운영하는 셈이었다.
수천 개의 조직이 정확히 그렇게 했다. 보안 연구자들은 몇 주 만에 28,000개 이상의 노출된 MongoDB 인스턴스를 발견했다1. 랜섬 요구액은 보통 0.2~1 비트코인으로 적당한 수준이었지만, 돈을 지불한 피해자 중 많은 수가 돈을 잃는 것보다 더 나쁜 사실을 발견했다: 공격자들은 데이터를 애초에 백업한 적이 없었다. 그들은 그냥 데이터를 삭제하고 다음 목표로 넘어갔다.
일부 데이터베이스에는 의료 기록이 담겨 있었다. 다른 것들에는 고객 데이터, 금융 거래, 수년간의 운영 기록이 들어 있었다. 모두 사라졌다.
기본 보안이 중요한 이유
MongoDB 개발팀은 버전 3.6에서 기본값을 수정했다2. 이제 데이터베이스는 기본적으로 로컬호스트(127.0.0.1)에만 바인딩되며, 관리자가 명시적으로 설정하지 않는 한 네트워크 연결이 거부된다.
하지만 이 교훈은 MongoDB를 훨씬 뛰어넘는다.
랜섬 공격이 성공한 것은 소프트웨어가 출시되는 방식과 프로덕션에서 실행되어야 하는 방식 사이의 간극 때문이었다. MongoDB의 원래 기본값은 개발자 편의성을 우선시했다—설치하고, 시작하고, 즉시 데이터 저장을 시작할 수 있었다. 별도의 설정이 필요 없었다. 그 편의성은 데이터베이스가 공용 네트워크에 연결되는 순간 취약점이 되었다.
모든 데이터베이스 포트는 문이다. 항상 던져야 할 질문은 이것이다: 누가 그 문을 열 수 있어야 하는가?
포트 27017 보안 설정
특별한 이유가 없다면 로컬호스트에만 바인딩하라. 애플리케이션이 MongoDB와 같은 서버에서 실행된다면, 데이터베이스가 127.0.0.1에서만 수신하도록 설정하라. 외부 연결이 불가능해진다. 네트워크 계층에서 문제가 해결된다.
원격 접근이 필요할 때는 방화벽을 사용하라. 특정 IP 주소만 허용 목록에 추가하라. 절대로 0.0.0.0/0(전체 인터넷)이 데이터베이스 포트에 접근하도록 허용하지 마라. 방어 계층을 겹쳐라: 운영 체제 방화벽, 클라우드 보안 그룹, 네트워크 ACL. 어느 한 계층이 뚫릴 수 있다고 가정하라.
항상 인증을 활성화하라. 필요한 최소 권한을 가진 사용자를 생성하라. 애플리케이션은 admin으로 연결되어서는 안 된다. 관리 자격증명은 신뢰할 수 있는 위치에서만 접근하는 실제 관리 작업을 위해 아껴두어라.
연결을 암호화하라. TLS는 전송 중인 데이터를 보호한다. 이는 패킷이 공유 인프라를 통과하는 클라우드 환경에서 특히 중요하다. 성능 부담은 미미하지만, 도청에 대한 보호 효과는 상당하다.
분산 배포에서의 추가 포트
MongoDB의 고가용성 기능은 보안을 설정해야 할 포트를 더 추가한다:
- 27018: 샤딩된 클러스터의 샤드 서버
- 27019: 클러스터 메타데이터를 저장하는 구성 서버
- 레플리카 셋 멤버: 데이터를 동기화하고 프라이머리를 선출하기 위해 설정된 포트(보통 27017)를 통해 통신한다
각 구성 요소에는 내부 클러스터 통신을 허용하면서 다른 모든 것을 차단하는 방화벽 규칙이 필요하다. 클러스터에 참여할 수 있는 MongoDB 인스턴스를 권한 있는 것으로만 제한하기 위해 키파일 인증이나 x.509 인증서를 사용하라.
클라우드 호스팅 MongoDB
MongoDB Atlas, AWS DocumentDB, Azure Cosmos DB 같은 관리형 서비스는 이 중 많은 부분을 자동으로 처리한다. 인터넷에 직접 노출되지 않는 프라이빗 네트워크 안에서 실행된다. VPC 피어링이나 IP 허용 목록을 통해 연결한다.
절충점이 있다: 일부 제어권을 잃지만, 인터넷이 적대적이라고 가정하는 기본 보안 설정을 얻는다. 많은 팀에게 이것이 올바른 선택이다.
더 큰 교훈
포트 27017은 그냥 숫자에 불과하다. 그 뒤에 있는 이야기—편의성 기본값이 개방된 인터넷을 만나 수만 개의 데이터베이스가 삭제된 것—는 당신이 노출하는 모든 서비스에 적용된다.
공격자들은 끊임없이 스캔한다. 봇은 모든 IP 주소, 모든 포트, 모든 프로토콜을 탐색한다. 문을 잠그지 않으면 누군가가 그것을 열 것이다. 보통 몇 시간 안에.
MongoDB 랜섬 공격은 취약점을 악용한 것이 아니었다. 설정의 허점을 파고든 것이었다. 데이터베이스는 설계된 대로 정확히 작동하고 있었다. 단지 배포된 환경에 맞게 설계되지 않았을 뿐이었다.
당신이 여는 모든 포트는 하나의 결정이다. 의도적으로 결정하라.
포트 27017에 관해 자주 묻는 질문
MongoDB는 왜 기본적으로 어디서든 연결을 허용했나?
MongoDB는 원래 개발자 경험을 우선시했다. 가장 쉬운 설정이란 인증 없이 모든 인터페이스에 바인딩하는 것을 의미했다—설치하고, 시작하고, 연결하면 됐다. 로컬 개발에서는 합리적이었지만, 개발자들이 공용 IP 주소가 있는 프로덕션 서버에 같은 설정을 그대로 배포하는 순간 재앙이 되었다.
MongoDB의 기본 포트를 변경할 수 있나?
그렇다. --port 플래그나 net.port 설정 옵션을 사용해 MongoDB가 임의의 포트에서 수신하도록 설정할 수 있다. 하지만 포트를 변경하는 것은 보안상 이점이 거의 없다(이른바 '모호성을 통한 보안'). 어떤 포트 번호를 선택하느냐보다 적절한 인증과 방화벽 규칙이 훨씬 더 중요하다.
MongoDB가 인터넷에 노출되어 있는지 어떻게 확인하나?
네트워크 외부에서 연결을 시도해 보라: mongo --host YOUR_PUBLIC_IP --port 27017. 연결이 된다면(인증이 실패하더라도), 포트에 접근 가능한 것이다. 더 좋은 방법은 Shodan 같은 서비스를 사용해 인터넷에서 당신의 인프라가 어떻게 보이는지 직접 확인하는 것이다.
MongoDB는 지금 사용하기 안전한가?
그렇다, 올바르게 설정하면. 현대 MongoDB의 기본값은 안전하다—로컬호스트 바인딩과 필수 인증. 랜섬 공격은 데이터베이스 자체의 근본적인 결함이 아니라 레거시 설정과 부주의한 배포를 노린 것이었다.
출처
이 페이지가 도움이 되었나요?