CVE-2019-14271

구름빵·2022년 1월 21일

개요

취약점 (버전)취약점 종류취약점 설명
Docker 19.03.0Full Container Escape* docker cp command를 통해 발생
일반 사용자가 취약점이 제대로 패치되지 않은 도커 컨테이너, 혹은 악성 컨테이너를 실행하고 docker cp 명령을 사용하게 되면 공격자가 해당 컨테이너에서 벗어나 host 파일의 모든 권한을 가지게 되며 다른 컨테이너로도 침입할 수 있게 된다.

배경지식

“docker cp” command

① from container to host

$ sudo docker cp containerID(name):/src/path /host/dst/path

② from host to container

$ sudo docker cp /host/src/path containerID(name):/dst/path

③ from containerA to containerB

$ sudo docker cp containerA:/src/path containerB:/dst/path

docker-tar relocation error

[ERROR] docker-tar relocation error

docker 19.03.0에서 docker cp 명령을 사용할 때 아래와 같은 오류가 발생한다.

Error response from daemon: error processing tar file: docker-tar: relocation error: /lib/x86_64-linux-gnu/libnss_files.so.2: symbol __libc_readline_unlocked, version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference: exit status 127

(Github Issue: https://github.com/moby/moby/issues/39449)

[SOLUTION] libnss libraries

특정 이미지에는 libnss 라이브러리 파일이 기본적으로 저장되어 있지 않다. 이러한 이미지의 컨테이너를 생성했을 때 docker cp를 실행하면 실패하고 crash가 일어나게 되는 것이다.

NSS(Name Service Switch)

NSS는 공통적인 설정 데이터베이스들과 name resolution 메커니즘들을 컴퓨터에 연결하도록 한다. → 이러한 소스 파일들은 '/etc/passwd', '/etc/group', '/etc/hosts'와 같은 파일들과 DNS, NIS, LDAP를 모두 포함한다.

- NSS Configuration File (/etc/nsswitch.conf: name service switch configuration file)

container 내부 nsswitch.conf
△ container 내부의 nsswitch.conf 파일

host의 nsswitch.conf
△ host의 nsswitch.conf 파일

files, db, dns, nis, nisplus 등의 서비스들을 사용한다.

⇒ 이러한 서비스(service)들의 코드는 libnss_*service*라는 이름의 모듈에 구현되어 있다.

→ 공유 라이브러리를 지원하는 시스템의 경우에는 libnss_*service*.so.2라는 이름으로 공유라이브러리로 사용된다.

container 내부 libnss library
△ 컨테이너 내부 libnss 라이브러리

host의 libnss library
host의 libnss library△ host의 libnss 라이브러리

위와 같이 각 서비스들에 대한 코드를 공유 라이브러리 형식으로 구현했다.


Root Cause 분석

도커는 Golang으로 작성되며, 특히 Go v1.11으로 컴파일 된 도커는 특히 취약하다. 이 버전의 경우, embedded C code (cgo)를 포함하고 있는 패키지들이 런타임 중 동적으로 공유 라이브러리들을 로딩할 수 있다.

이 패키지들은 net과 os/user를 포함하고, 둘 다 docker-tar 프로세스에 의해 사용되며, 런타임 중 libnss_*.so 라이브러리들을 로딩한다.

  • net, os/user: go 모듈
  • docker-tar: helper process
  • libnss_*.so: 동적 공유 라이브러리

일반적으로 라이브러리들은 host 파일 시스템에서 로딩되지만, docker-tar에 의해 컨테이너로 chroot 되면서, 컨테이너 파일 시스템으로부터 라이브러리들을 로딩하도록 바뀐다.

즉, docker-tar는 컨테이너에 의해 생성되고 관리되는 코드들을 로딩하고 실행한다는 것이다.

docker cp container → host 의 과정은 다음과 같다.

① 컨테이너 내부로 root (디렉터리)를 변경한다.

docker-tar
docker-tar 프로세스의 root가 docker container fs를 가리키고 있다

② 요청한 파일들과 디렉터리를 바뀐 root(/proc/docker-tarPID/root)에 저장하고, 이 때 tar 파일로 묶어서 저장한다. (이는 압축하는 것과는 다르다.)

③ 해당 tar 파일을 도커 데몬에 다시 전달하는데, 이 때 이 도커 데몬은 호스트의 지정한 디렉터리에 tar 파일을 풀어 저장한다.

주의할 점은, 컨테이너 파일 시스템으로 chroot 된다는 점 외에는 docker-tar가 컨테이너화되는 것이 아니다.

  • host namespace에서 모든 root 권한을 가지고 돌아간다.

  • cgroups, seccomp에 의해 제한되지 않는다.

따라서, docker-tar에 코드 인젝션을 통해 악성 컨테이너가 host에 대한 전체 root 권한을 얻을 수 있다.

Docker 사용자가 다른 환경(host/다른 container)에서 파일을 복사해올 수 있는 공격 시나리오는 아래와 같다.

  • 잘못된 libnss_*.so 라이브러리를 가지고 있는 악성 이미지를 실행 중인 컨테이너
  • 공격자가 libnss_*.so 라이브러리들을 바꿔치기한 취약한 컨테이너

위의 두 가지 경우, 공격자가 호스트에 대해 root 권한으로 코드 실행을 할 수 있다.


Exploit 과정 (재연X)

ⓐ libnss 라이브러리 수정

ⓑ breakout script 작성

#!/bin/bash

1 umount /host_fs && rm -rf /host_fs
2 mkdir /host_fs


3 mount -t proc none /proc     # mount the host's procfs over /proc
4 cd /proc/1/root              # chdir to host's root
5 mount --bind . /host_fs      # mount host root at /host_fs
6 echo "Hello from within the container!" > /host_fs/evil

△ container 내부에서 작성한 breakout.sh

host file system을 컨테이너 내부의 '/host_fs'에 마운트하도록 하고, host의 '/evil'에 메시지를 적는 스크립트다.

ⓒ Dockerfile 작성

ⓓ Exploit


패치 내용

docker-patch

문제가 되었던 Go 패키지로부터 임의의 함수를 호출하는 docker-tar의 초기화 함수를 수정하며 취약점에 대한 내용을 보완했다. 이로 인해 docker-tar는 container에서 chroot 하기 전에 libnss 라이브러리를 로드하게 되며, 호스트의 파일 시스템으로부터 로드한다.


참고자료

NVD, CVE Details, link

Tenable, PoC of CVE-2019-14271, link

Github, Docker Issue, link

PaloaltoNetworks, Unit42, docker patch, link

profile
ฅʕ•̫͡•ʔฅ

0개의 댓글