Skip to content

Instantly share code, notes, and snippets.

@leoh0
Last active December 30, 2019 00:23
Show Gist options
  • Save leoh0/bc466e6daaf3f249c715da218009a102 to your computer and use it in GitHub Desktop.
Save leoh0/bc466e6daaf3f249c715da218009a102 to your computer and use it in GitHub Desktop.
CVE-2019-5736 poc 와 해결방법을 정리 했습니다.

CVE-2019-5736

설명

이 취약점은 악의적인 사용자가 컨테이너(runc를 사용하는 docker 등)를 사용해서 호스트 시스템의 runc 바이너리를 변조하여 root 억세스를 가능하게 합니다. 자세한내용은 redhat을 참고하시면 좋습니다.

POC

이 부분은 시스템에 문제를 발생시킬 수 있습니다. 정확한 이해나 관리가 가능할때 테스트 해보고 사용하시길 권장드립니다.

이 poc는 runc (docker 이용시 docker-runc) 바이너리에 변조를 가져옵니다. 미리 백업을 하시고 진행하셔야 합니다.

docker-runc 이용시 백업

cp /usr/bin/docker-runc /usr/bin/docker-runc.orig.$(date -Iseconds)

runc 이용시 백업

cp /usr/bin/runc /usr/bin/runc.orig.$(date -Iseconds)

docker 이용시 poc 입니다.

$ # 바이너리의 원래 상태를 확인 합니다.
$ tail -c100 /usr/bin/docker-runc | xxd
00000000: 0000 0000 a2cf 0600 0000 0000 0000 0000  ................
00000010: 0000 0000 0100 0000 0000 0000 0000 0000  ................
00000020: 0000 0000 1100 0000 0300 0000 0000 0000  ................
00000030: 0000 0000 0000 0000 0000 0000 1aca a600  ................
00000040: 0000 0000 de01 0000 0000 0000 0000 0000  ................
00000050: 0000 0000 0100 0000 0000 0000 0000 0000  ................
00000060: 0000 0000                                ....

$ # poc를 진행 합니다.
$ docker run leoh0/cve-2019-5736-poc
Unable to find image 'leoh0/cve-2019-5736-poc:latest' locally
latest: Pulling from leoh0/cve-2019-5736-poc
6cf436f81810: Already exists
987088a85b96: Already exists
b4624b3efe06: Already exists
d42beb8ded59: Already exists
92688bb38886: Pull complete
1a676e32195d: Pull complete
33bc4ebfeb17: Pull complete
e124b3a73eaa: Pull complete
7731fea1d8f0: Pull complete
2e33272ce7fe: Pull complete
Digest: sha256:360fb3b03a65860f4cdd4c0256c512bcc18d732215d83bdf356b7b522fbbd99d
Status: Downloaded newer image for leoh0/cve-2019-5736-poc:latest
HAX2: argv: /proc/self/fd/3
HAX2: fd: 4
HAX2: res: 13, 0

$ # 변조된 바이너리의 원래 상태를 확인 합니다.
$ tail -c100 /usr/bin/docker-runc | xxd
00000000: 0000 0000 0000 0001 0000 0000 0000 0000  ................
00000010: 0000 0000 0000 0011 0000 0003 0000 0000  ................
00000020: 0000 0000 0000 0000 0000 0000 0000 001a  ................
00000030: caa6 0000 0000 00de 0100 0000 0000 0000  ................
00000040: 0000 0000 0000 0001 0000 0000 0000 0000  ................
00000050: 0000 0000 0000 0063 7665 2d32 3031 392d  .......cve-2019-
00000060: 3537 3336                                5736

만약 백업이 안되었으면 아래를 참고해서 마지막 문자열을 제거 합니다.

$ truncate -s-13 /usr/bin/docker-runc

$ tail -c100 /usr/bin/docker-runc | xxd
00000000: 0000 0000 a2cf 0600 0000 0000 0000 0000  ................
00000010: 0000 0000 0100 0000 0000 0000 0000 0000  ................
00000020: 0000 0000 1100 0000 0300 0000 0000 0000  ................
00000030: 0000 0000 0000 0000 0000 0000 1aca a600  ................
00000040: 0000 0000 de01 0000 0000 0000 0000 0000  ................
00000050: 0000 0000 0100 0000 0000 0000 0000 0000  ................
00000060: 0000 0000                                ....

해결방법

upgrade

아래의 버전으로 runc 혹은 docker upgrade

Ubuntu - runc 1.0.0~rc4+dfsg1-6ubuntu0.18.10.1
Debian - runc 1.0.0~rc6+dfsg1-2
RedHat Enterprise Linux - docker 1.13.1-91.git07f3374.el7 (if SELinux is disabled)
Amazon Linux - docker 18.06.1ce-7.25.amzn1.x86_64
CoreOS - Stable: 1967.5.0 / Beta: 2023.2.0 / Alpha: 2051.0.0
Kops Debian - in progress
Docker - 18.09.2
Containerd - 1.2.4

upgrade가 용의치 않을때

이 부분은 시스템에 문제를 발생시킬 수 있습니다. 정확한 이해나 관리가 가능할때 테스트 해보고 사용하시길 권장드립니다.

k8s와 같이 docker의 낮은 버전을 쓰는 상태에서는 runc의 바이너리만 바뀌어야 하나 runc자체가 docker 안에 패키지 되어 있어서 docker-ce 버전에서는 지원이 안될 것 같습니다. 그래서 이와 같이 runc 바이너리(docker-runc)만 업데이트 하는 경우를 고려해야 할 수 있습니다.

rancher 에서 생성해둔 runc 빌드를 이용해서 runc binary를 빌드후 runc 바이너리를 업데이트 합니다. 다만 여기의 runc binary 들은 static build 입니다. rancher와 같이 systemd cgroup을 사용하지 않을때는 관계없지만 만약 systemd cgroup을 사용하면 아래의 에러가 발생 합니다.

# docker run --rm ubuntu echo OK
docker: Error response from daemon: OCI runtime create failed: systemd cgroup flag passed, but systemd support for managing cgroups is not available: unknown.

이때는 이 레포지토리를 참고해서 dynamic build해서 runc 바이너리를 빌드해야 합니다. 왜냐하면 runc는 static build일때 systemd cgroup을 사용하지 않도록 설정되어 있습니다.

$ # static build일때
$ ldd runc-v17.12.1-amd64
    not a dynamic executable
$ # non-static build일때
$ ldd runc-v17.12.1-amd64-nonstatic
    linux-vdso.so.1 =>  (0x00007ffcd05fa000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f742f766000)
    libseccomp.so.2 => /lib64/libseccomp.so.2 (0x00007f742f525000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f742f321000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f742ef54000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f7430412000)

static build 이용시

# Figure out where your docker-runc is, typically in /usr/bin/docker-runc
which docker-runc

# Backup
mv /usr/bin/docker-runc /usr/bin/docker-runc.orig.$(date -Iseconds)

# Copy file
cp runc-v17.06.2-amd64 /usr/bin/docker-runc

# Ensure it's executable
chmod +x /usr/bin/docker-runc

# Test it works
docker-runc -v
docker run -it --rm ubuntu echo OK

dynamic build 이용시 (systemd cgroup 사용시)

# Figure out where your docker-runc is, typically in /usr/bin/docker-runc
which docker-runc

# Backup
mv /usr/bin/docker-runc /usr/bin/docker-runc.orig.$(date -Iseconds)

# Copy file
cp runc-v17.06.2-amd64-nonstatic /usr/bin/docker-runc

# Ensure it's executable
chmod +x /usr/bin/docker-runc

# Test it works
docker-runc -v
docker run -it --rm ubuntu echo OK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment