
CVE-2024-21626에 대한 개념 증명, runc 컨테이너 탈출 취약점. 검증 스크립트, 두 가지 악용 방법(cron 리버스 셸 및 명령어 교체), 그리고 근본 원인과 패치 분석을 포함합니다.
| 취약점 이름 | docker runc 탈출 취약점 |
|---|---|
| 취약점 번호 | CVE-2024-21626 |
| 공개 날짜 | 2024-01-31 |
| 특징 | / |
| 영향받는 버전 | runc @ [v1.0.0-rc93,1.1.11] |
이용 조건은 다소 까다롭고 피해자의 상호작용이 필요하며, 개인적으로는 계륵(있으나 마나 한)이라고 생각합니다:
취약점 존재 검증 및 파일 디스크립터 확인:
git clone https://github.com/V0WKeep3r/CVE-2024-21626-runcPOC.git
cd CVE-2024-21626-runcPOC
bash verify.sh
아래 그림과 같이 취약점이 존재하며, 파일 디스크립터는 /proc/self/fd8입니다.
verify.sh는 현재 머신 환경에 대응하는 fd의 구체적인 값을 찾아낼 수 있습니다. fd가 8이 아닐 경우 Dockerfile의 WORKDIR을 해당 값으로 수정하거나 docker run에서 -w로 지정해야 합니다.
탈출/권한 상승 검증: 여기서는 실전에 더 가깝게 구성했습니다. poc.sh는 cron 작업을 사용하여 리버스 셸을 띄웁니다. poc2.sh는 명령어 교체 방식을 사용합니다(주의: 이 방식을 사용할 경우 파일을 미리 백업해 두어야 파일 복구가 어렵지 않습니다).
# 需要确认定时任务文件存在,不存在可以创建写,但是那样不能触发定时任务
# 只有crontab -e创建的,在crontab组的文件才会被定时执行。
docker build . -t poc1
docker run -it --rm poc1 bash /poc.sh

POC2:
docker build . -t poc2
docker run -it --rm poc2 bash /poc.sh
# 另起一个terminal
/bin/bash.copy

완전히 이해한 것은 아니지만, 패치와 함께 보면 대략적인 파악이 가능합니다.
docker exec 또는 docker run 과정에서 runc의 execve 함수가 호출됩니다. 그런데 runc exec 과정에서 fd 파일 디스크립터를 닫지 않아 호스트 머신의 파일 디스크립터가 컨테이너 환경에도 함께 누출됩니다. 사용자는 이 파일 디스크립터를 통해 호스트 머신의 파일을 읽고 쓸 수 있으며, 이를 통해 컨테이너 탈출을 수행할 수 있습니다.
수정 방안 runc를 1.12 이상으로 업그레이드합니다. runc 공식 링크: https://github.com/opencontainers/runc/releases
패치 분석
diff commit: https://github.com/opencontainers/runc/commit/2a4ed3e75b9e80d93d1836a9c4c1ebfa2b78870e
execve 실행 전에 내부 fds를 제때 닫습니다
init_linux.go는 chdir 이후 cwd(현재 작업 디렉터리)가 컨테이너 내부에 있는지 검증합니다
