데스크탑에 나도 모르게 채굴 프로그램이 설치되어 있었던 이야기

아 너무 무섭다

2019. 09. 07. #security #diary

서론

이 이야기는 9월 8일 새벽, 태풍이 지나간 뒤의 선선한 바람을 쐬며 평화롭게 코딩을 하던 도중 일어난 이야기입니다.

저는 새로 작업한 기능의 유닛 테스트를 한 번에 통과시키며 기분 좋게 작업을 하고 있었습니다. 당시 유튜브에서는 작업용 BGM으로 은토님의 SOMANUS가 흘러나오고 있었죠. (넥슨 게임은 거의 하지도 않고 관심도 없지만 노래 만큼은 좋아합니다.)

노래가 하이라이트로 들어가기 시작할 때 쯤, 갑자기 데스크탑이 미친듯이 느려지더니 흘러나오던 노래는 글리치에 걸린 듯 섬뜩하게 깨지기 시작했습니다. 하고있는 작업이라고는 간단한 TypeScript 서버를 만지작거리던 것 뿐인데 말이죠. 라이젠 2700X에 RTX 2060 쓰고 있으니 데스크톱 사양이 그렇게 부족한 것도 아니었습니다.

처음에는 그냥 제가 작업한 곳에 무한루프 같은 버그가 있었겠거니 하고 가벼운 마음으로 ps를 쳤습니다. 그런데 CPU를 가장 많이 차지하고 있었던 프로세스 이름은 다름아닌 모네로(XMR) 코인의 채굴 프로그램, xmrig 였습니다. (너무 놀라서 캡쳐를 못했어요...)

어디서 뚫고 들어온거지?

저는 암호화폐 채굴이나 투자, 블록체인 관련 개발을 전혀 하지 않습니다. 당연히 컴퓨터에 채굴기 같은 것을 깔아본 적도 없습니다. 그러면 저 xmrig는 제가 아닌 다른 누군가가 설치했다는 이야기가 됩니다. 제 데스크탑은 SSH 서버가 특정 포트로 열려있긴 하지만, 당연히 접속할 때 개인 PEM키로 인증 절차를 밟고 있습니다. 그럼 PEM키가 유출이라도 된걸까요? 갑자기 소름이 돋고 식은 땀이 흐르기 시작했습니다.

일단 침착하게 xmrig가 어디에 숨어있는지부터 찾아봅시다.

find / -name xmrig

경로가 도커 볼륨으로 되어있습니다. 그럼 공격자는 제 데스크탑에 접속해서 굳이 docker 컨테이너를 띄워 채굴기를 실행한걸까요? 조금 이상하다는 생각이 들긴 했지만, 뭐 의존성 관리를 신경쓸 필요가 사라지니 그럴 수도 있겠구나 하고 넘어갔습니다. 아무튼 어떤 컨테이너가 돌고 있는지 확인해봅시다.

docker ps

프로세스를 몇 번 강제로 죽이고 나서 캡쳐한거라 Exited가 몇 개 있습니다.

tanchao2014/mytest 라는 듣도보도 못한 이미지로 컨테이너가 실행되고 있었습니다. 이 이미지 이름으로 구글에 검색을 해보니, 5일 전에 작성된 딱 하나의 글 (중국어, CC BY-SA 4.0)이 있었습니다. 번역기의 힘을 빌어 천천히 읽어 내려가다보니, 어디가 문제였는지 바로 알 수 있었습니다.

보안 홀은 바로 Docker Daemon 소켓

Docker는 에이전트와 클라이언트 간의 통신에 기본적으로는 UNIX 소켓을 이용합니다. 하지만 원격 환경에서도 쉽게 접근할 수 있도록 TCP 통신을 이용해 에이전트에 접근하는 방법 또한 존재합니다.

얼마 전에 LYnLab Luppiter 관련 서비스를 개발하면서, API 서버와 도커 노드간의 통신을 위해 로컬과 운영 환경의 Docker 에이전트에 TCP 소켓을 설정했습니다. 그 과정에서 로컬에서는 테스트를 빨리빨리 해보기 위해 별도의 인증 레이어를 두지 않았던 것이 화근이었습니다.

공격자는 아마 여러 IP를 돌며 2375번 포트가 열려있는 IP를 검색했을 것이고, 그 중에 저처럼 인증을 거치지 않는 에이전트들을 찾아 API를 통해 채굴 프로그램이 설치된 컨테이너를 띄웠을 겁니다. 아마 지금도 어딘가의 컴퓨터에서는 이 사람을 위한 채굴기가 열심히 일을 하고 있겠죠.

근본적인 원인을 찾았으니 문제 해결은 간단했습니다. 일단 로컬에서 돌고 있는 채굴 컨테이너를 모두 내리고, 이미지를 삭제해줍니다.

docker rm <container_id>
docker rmi tanchao2014/mytest

그리고 원격에서 더 이상 접근하지 못하도록 Docker 에이전트의 TCP 소켓을 닫아주었습니다.

sudo vim /etc/docker/daemon.json  # 불필요한 TCP 소켓 옵션 제거

sudo systemctl stop docker
sudo systemctl daemon-reload
sudo systemctl start docker

추가로 데스크탑의 외부 IP 주소를 변경하는 작업을 진행할 예정입니다.

문제점과 해결 과정 되짚어보기

방화벽은 없었는가?

솔직히 서버가 아닌 데스크탑이다보니 보안에 둔감했던 점도 없지 않았습니다.

외부 네트워크에서 제 데스크탑에 도달하기까지 방화벽이 있을만한 곳은 공유기와 데스크탑, 두 군데가 있습니다. 아쉽게도 공유기는 밑에 개인 서버가 물려있다보니 대부분의 포트가 열려있었고, 데스크탑에는 아예 방화벽 세팅이 되어있지 않았습니다. 특히 데스크탑 방화벽의 경우, 나중에 셋팅해야지 하고 미루고 미루다가 결국 이런 사건이 터지게 되었네요.

실 서비스에 보안 문제는 없는가?

당연히 실 서비스 중인 Docker 에이전트에는 인증 과정이 적용되어있고, VPC 외부에서 직접 접근하는 것이 불가능합니다. 그래도 혹시 몰라 모든 Docker 에이전트 서버를 점검해보았고, 아무런 이상이 없음을 확인했습니다.

비슷한 유형의 다른 보안 홀은 없는가?

로컬에서 개발을 위해 간헐적으로 띄우는 서버는 큰 문제가 없을 것이라 생각합니다. 다만 지금 생각해보면 Docker가 열려있다는 것 자체가 정말 심각한 보안 홀이었습니다. 조금만 생각해봐도, 컨테이너를 호스트 경로에 마운트해서 파일을 탈취하는 등의 치명적인 행동 또한 가능해보입니다.

다행히 지금까지 로컬 개발 환경에 보안이 중요한 데이터를 저장한 적은 없습니다. 다만 추후에도 로컬 환경에 민감한 데이터가 포함되지 않도록 유의해야할 것이며, 근본적으로는 방화벽으로 외부에서의 접근 자체를 막아야겠지요.

교훈

보안에 대해서는 꽤 신경을 쓰는 편임에도 불구하고, 조금의 귀찮음 때문에 어이없게도 제 데스크탑을 이름도 모르는 사람에게 마이닝 머신으로 갖다 바치고 말았습니다. 그나마 다행인 것은 공격자가 xmrig 라는 이름을 숨기지 않고 당당하게 채굴을 한 덕분에 빠르게 원인을 찾을 수 있었고, 문제가 꽤나 심각했다는 점에 비해서는 큰 피해가 없었다는 점입니다.

만약 이것이 운영중인 서비스나 개인정보가 포함된 서버에서 일어난 일이었다면 아주 큰 피해로 이어졌을지도 모릅니다. 이번 일을 계기로, 단지 귀찮다는 이유로 개발 환경에서의 보안 조치를 허술히했던 점에 대해 반성하게 되었습니다.

보안은 들이는 시간과 노력에 비례하여 강력해집니다. 이 글이 여러분들에게 각자의 컴퓨터나 서버에 외부인들에게 활짝 열려있는 경우는 없는지, 방화벽은 잘 갖추어져 있는지 등을 다시금 살펴보는 기회가 되었으면 좋겠습니다.

크리에이티브 커먼즈 라이선스

이 저작물은 크리에이티브 커먼즈 저작자표시-동일조건변경허락 4.0 국제 라이선스에 따라 이용할 수 있습니다.

© 2011 - 2020 Do Hoerin, LYnLab