Docker 보안: 발생하지 않은 사건들
Docker 보안: 발생하지 않은 사건들 (non-events)
이 페이지는 Docker가 기본 설정만으로 이미 차단해 버려서, 실제로 컨테이너 안에서 실행 중인 프로세스가 피해를 입을 일이 없었던 보안 취약점들을 정리한 목록이에요. 여기서 말하는 기본 설정은 추가적인 capability를 주지 않거나 --privileged 모드로 실행하지 않는 일반적인 환경을 전제로 해요. 아래 목록은 모든 사례를 담은 게 아니라 공개적으로 알려진 취약점 중 일부를 뽑은 표본일 뿐인데, Docker의 secure by default 접근법 덕분에 알려지지 않은 버그도 비슷하게 잘 막힐 가능성이 커요.
출처: 공식문서
본문
Docker가 차단한 취약점 (Bugs mitigated)
- CVE-2013-1956, 1957, 1958, 1959, 1979, CVE-2014-4014, 5206, 5207, 7970, 7975, CVE-2015-2925, 8543, CVE-2016-3134, 3135 등:
비특권 사용자 네임스페이스(unprivileged user namespaces)가 도입되면서, 평범한 사용자도
mount()처럼 원래 root만 쓸 수 있던 시스템 콜을 합법적으로 호출할 수 있게 되면서 공격 표면(attack surface)이 크게 넓어졌어요. 위 CVE들은 전부 사용자 네임스페이스 도입 때문에 생긴 보안 취약점 사례들이죠. Docker는 사용자 네임스페이스로 컨테이너를 구성할 수 있지만, 기본 seccomp 프로필을 통해 컨테이너 내부 프로세스가 자신만의 중첩 네임스페이스를 새로 만들지 못하도록 막아서 이런 취약점을 악용할 수 없게 만들었어요. - CVE-2014-0181, CVE-2015-3339:
이 버그들은 setuid 바이너리가 있어야만 악용할 수 있는 취약점이에요. Docker는
NO_NEW_PRIVS프로세스 플래그와 다른 메커니즘을 통해 컨테이너 안에서 setuid 바이너리를 아예 비활성화해 버려요. - CVE-2014-4699:
ptrace()의 버그로 권한 상승이 가능했던 사례예요. Docker는 apparmor, seccomp, 그리고CAP_PTRACE제거를 통해 컨테이너 안에서ptrace()를 차단해요. 보호 계층이 무려 세 겹이나 되는 셈이죠! - CVE-2014-9529:
정교하게 조작된
keyctl()호출로 커널 DoS나 메모리 손상을 일으킬 수 있었던 취약점이에요. Docker는 seccomp를 이용해 컨테이너 안에서keyctl()을 차단해요. - CVE-2015-3214, 4036:
가상화 드라이버에서 발견된 버그로, 게스트 OS 사용자가 호스트 OS에서 코드를 실행할 수 있었던 사례들이에요. 이 취약점을 악용하려면 게스트 안에서 가상화 장치에 접근할 수 있어야 하는데, Docker는
--privileged없이 실행하면 이런 장치들에 대한 직접 접근을 숨겨 버려요. 흥미롭게도, 이 사례들은 "VM이 컨테이너보다 더 안전하다"는 통념과 달리 컨테이너가 VM보다 더 안전한 경우라고 할 수 있어요. - CVE-2016-0728:
조작된
keyctl()호출로 use-after-free가 발생해 권한 상승으로 이어질 수 있었던 취약점이에요. Docker는 기본 seccomp 프로필로 컨테이너 안에서keyctl()을 차단해요. - CVE-2016-2383:
eBPF, 그러니까 seccomp 필터 같은 것을 표현할 때 쓰는 커널 내부 특수 DSL에서 발견된 버그로, 커널 메모리를 임의로 읽을 수 있었던 취약점이에요.
bpf()시스템 콜은 (역설적이게도) seccomp를 사용해서 Docker 컨테이너 안에서 차단돼요. - CVE-2016-3134, 4997, 4998:
IPT_SO_SET_REPLACE,ARPT_SO_SET_REPLACE,ARPT_SO_SET_REPLACE인자와 함께setsockopt를 호출할 때 메모리 손상이나 로컬 권한 상승이 발생했던 버그들이에요. 이런 인자들은CAP_NET_ADMIN이 있어야 사용할 수 있는데, Docker는 기본적으로 이 capability를 허용하지 않아요.
Docker가 차단하지 못한 취약점 (Bugs not mitigated)
- CVE-2015-3290, 5157:
커널의 NMI(비마스크 가능 인터럽트) 처리 버그로 권한 상승이 가능했던 취약점이에요.
modify_ldt()시스템 콜이 현재 seccomp로 차단되어 있지 않아서 Docker 컨테이너 안에서도 악용될 수 있었어요. - CVE-2016-5195:
리눅스 커널 메모리 서브시스템이 private 읽기 전용 메모리 매핑의 COW(쓰기 시 복사)를 깨뜨릴 때 발생하는 경쟁 조건(race condition) 때문에, 비특권 로컬 사용자가 읽기 전용 메모리에 쓰기 접근 권한을 얻을 수 있었던 취약점이에요. "dirty COW"라고도 알려져 있죠.
부분 완화: 일부 운영체제에서는 seccomp의
ptrace필터링과/proc/self/mem이 읽기 전용이라는 사실이 결합되어 이 취약점이 완화되기도 해요.