이 글은 해킹을 권장하거나 조장하는 목적이 전혀 없습니다.
오직 정보 전달을 위한 목적으로 작성되었으며, 이 내용을 바탕으로 발생하는 모든 행동에 대한 책임은 전적으로 당사자에게 있음을 명확히 고지합니다.
(Spring 기준) 요즘 배포를 할때 직접 jar파일을 배포하는 경우가 잘 없고 컨테이너 형식의 이미지를 배포한다고 생각합니다. 저도 도커를 사용해서 많은 프로젝트를 배포하였고 지금도 잘 사용하고 있습니다.
하지만 도커, 잘못 사용한다면 매우 큰 보안의 문제가 발생할 수 있습니다!!!
보통 스프링의 경우엔 파일의 환경변수를 yml or properties 파일에서 가져와 쓰고 환경변수 파일은 .gitignore를 한 뒤 깃허브에 커밋을 하여 환경변수에 DB정보, AWS 계정 정보 api Key등을 노출되지 않도록 합니다. 실제로 깃허브에 AWS 시크릿 정보를 노출한다면 바로 그 키는 정지되며 이메일로 알림이 올정도로 심각한 문제이죠.
(AWS 계정이 털려 GPU 서버 1시간만 돌려도 몇십 ~ 몇백은 깨집니다.)
(IAM 권한이 S3 한정이라면... 잘하셨습니다!!)
보통의 개발자들이라면 도커이미지를 빌드한 후 도커허브에 올린 뒤 EC2나 클라우드 서비스에 접속하여 도커를 pull 받은 후 실행시킬껍니다.
이 과정에서 심각한 문제가 있습니다.
또한 도커허브에선 이미지를 쉽게 찾을 수 있도록 검색기능을 지원합니다.
보통 사용자 이름은 깃허브 아이디랑 비슷할꺼고 저장되는 컨테이너 이미지는 서비스 이름일테니..
대충 이름 + 서비스 이름 검색하면 이미지가 나오겠죠? (사회공학기법)
이게 또 우리가 업로드한 이미지를 찾아 공격대상으로 만들 수 있는 양날의 검으로 작용할 수도 있습니다...
도커허브뿐만 아니라 오픈되어 있는 이미지 저장소는 위험할 수도 있는거죠
도커 허브의 이미지를 업로드 하면 기본적으로 퍼블릭이라 누구든지 pull을 받을 수 있습니다.
퍼블릭으로 바꿀수 있지만 무료계정은 계정당 1개만 프라이빗이 가능하고 나머진 퍼블릭으로 쓸 수 밖에 없죠.
퍼블릭 이미지를 pull 받고 도커 이미지를 디컴파일을 하면 .jar파일을 얻을 수 있습니다.
.jar 파일을 뜯으면 빌드과정에서 들어가있던 yml or properties 파일을 얻을 수 있죠.
(디컴파일 과정과 .jar 파일을 뜯는 과정은 악용될 수 있어 뭉둥거려서 이야기하겠습니다)
도커가 살려달라고 울부짖고 있어요 ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠ
해결방법은 사실 굉장히 간단합니다.
도커 허브에서 이미지를 퍼블릭 -> 프라이빗으로 바꾸는거죠
도커 허브에 접속해 바꾸고 싶은 이미지 하나를 클릭 후
세팅을 누른 뒤 아래로 내려 private 로 바뀌줍니다.
하지만 무료 계정은 하나만 priavte가 가능합니다 근본적인 yml 노출 문제는 여전히 존재하죠
저희팀에서 사용은 안해봤지만 yml 파일 암호화 방법 (Spring) 이런 방법도 있다고 하니 참고해보세요.
저희팀에서도 퍼블릭으로 도커허브에 프로젝트를 올린 상태라 이슈를 알게 되었고 조치를 취한 상태입니다.
(개인 도커허브의 이미지도 21개나 지웠습니다..ㅠ)
회사 내부에서 사용할땐 도커 프로의 엔터프라이즈 플랜을 사용할수도 있지만 개인 저장소를 구축해 사용하는 방법도 있습니다.
남는 VM 자원이 있다면 직접 구축하는 것도 좋은 경험이라 생각합니다.
위 방법이 부담스럽다면 클라우드 업체에서 운영하는 개인 저장소를 만들어 사용하는 방법도 있습니다.
비용이 그렇게 부담스럽진 않습니다.
Spring Cloud Config를 사용해 yml을 외부에서 가져와 사용하도록 할 수 있습니다.
이 기능까진 꼭 필요한가 생각합니다? (개인적인 의견)
도커 아이디와 비밀번호를 알아볼 수 없는 형태로 만들어 무슨 도커 이미지인지 파악하지 못하게 하는 방법도 있습니다.
asdjwid/sajdasj 이런식으로 말이죠
근본적인 문제를 해결하는 방법은 아니지만 실제 공격자들이 털어도 별 의미없는 서버인 경우 그냥 이렇게 하는것도 나쁘지 않다 생각합니다.
아님 그냥 당당하게 털리고 AWS한테 돈 못내 배째!!! 합시다 ㅎㅎ
사실 프로젝트가 기업 급이 아니고 개인 프로젝트들이라면 타겟이 되어 공격당하는 경우가 적을 거라 생각이 들지만, 만일의 상황을 대비해서 대처를 하는 게 개발자들의 자세가 아닐까요?
저희 서버개발자들은 언제 터질지 모르는 작은 EC2를 보며 매일 기도하는데 이 정도 작업은 껌이라 생각합니다.
또 이런 기술에 대한 문제를 알게 될 때마다 기술이 주는 좋은 점뿐만 아니라 안 좋은 점도 알아야 한다고 생각이 드는군요.
딸깍 (서버털리는소리)
api key 는 private, public 구분하지 않고 절대로 yaml에 그대로 쓰면 안됩니다.
클라우드 연동 포인트는 전부 환경 변수로 처리하고 Github action의 Actions secrets and variables 을 활용
또는 Jasypt 라는 라이브러리를 활용해서 암호화 하는 방법을 추천드립니다.
저는 개인적으로 전부 환경변수로 처리하고 Github Action이나 Ecs의 환경변수 주입 기능을 활용합니다.