
PoC: CVE-2026-31431 페이지 캐시 손상 + 공유 이미지 레이어를 통한 Kubernetes에서 완전 비특권 컨테이너 이스케이프에서 노드 수준 코드 실행까지. Alibaba Cloud ACK, Amazon EKS 및 Google GKE에서 검증됨.
공유 컨테이너 이미지 레이어를 통해 CVE-2026-31431 리눅스 커널 페이지 캐시 손상 버그를 악용하여 완전히 권한이 없는 컨테이너가 Kubernetes에서 노드 수준 코드 실행을 달성할 수 있는 방법을 보여주는 개념 증명입니다.
핵심 공격 원리는 다음과 같습니다: 공격자가 제어하는 컨테이너와 이미지 레이어를 공유하는 모든 권한 있는 DaemonSet이 컨테이너 탈출에 무기화될 수 있습니다. 이 PoC는 kube-proxy를 구체적인 예로 사용하지만, 이 기술은 클러스터의 모든 권한 있는 워크로드에 일반화됩니다.
Alibaba Cloud ACK, Amazon EKS, Google GKE에서 검증됨 — 권한 없는 파드가 권한 있는 kube-proxy DaemonSet을 통해 호스트 파일 시스템에 [*] success를 기록합니다:
| Alibaba Cloud ACK (커널 6.6.88) | Amazon EKS (커널 6.12.79) | Google GKE (커널 6.12.68) |
|---|---|---|
![]() | ![]() | ![]() |
면책 조항: 이 저장소는 교육 및 방어 목적으로만 게시됩니다. 귀하가 소유하거나 테스트할 명시적 권한이 있는 시스템에서만 사용하십시오.
CVE-2026-31431 ("Copy Fail")은 페이지 캐시 Copy-on-Write(CoW) 경로의 리눅스 커널 취약점입니다. AF_ALG splice 경합 조건을 통해 권한 없는 프로세스가 읽기 전용 파일의 페이지 캐시 페이지를 손상시킬 수 있습니다. 손상은 커널 페이지 캐시에 지속되며 이후 그 파일을 읽거나 실행하는 모든 프로세스(다른 컨테이너나 호스트의 프로세스 포함)에서 볼 수 있습니다.
원래 취약점에 대한 자세한 내용은 copy.fail을 참조하세요.
이 공격은 Kubernetes 클러스터에서 일반적으로 공존하는 세 가지 속성을 악용합니다:
privileged: true, hostNetwork: true, 광범위한 capabilities 등)으로 DaemonSet을 실행하며, 이들은 주기적으로 이미지에서 바이너리를 실행합니다.이러한 조건이 일치하면, 권한 없는 파드가 공유 이미지 레이어의 바이너리를 손상시킬 수 있고, 동일한 노드의 권한 있는 DaemonSet이 손상된 바이너리를 상승된 권한으로 알지 못한 채 실행하여 완전한 노드 수준 코드 실행을 달성합니다.
취약점 대상은 kube-proxy에 국한되지 않습니다. 공격자가 제어하는 이미지와 이미지 레이어를 공유하는 모든 권한 있는 DaemonSet(모니터링 에이전트, CNI 플러그인, 로그 수집기, 보안 에이전트 등)이 실행 가능한 대상입니다.
공격 체인은 세 단계로 구성됩니다: 페이지 캐시 손상, 컨테이너 간 전파, 권한 있는 실행.
커널의 AF_ALG(암호화) 서브시스템은 사용자 공간 암호화 작업을 위한 소켓 기반 인터페이스를 제공합니다. 익스플로잇은 커널이 파일에서 AF_ALG 소켓으로 splice()를 처리하는 방식의 경합 조건을 남용합니다:
authencesn(hmac(sha256),cbc(aes))에 바인딩된 AF_ALG AEAD 소켓을 생성합니다.MSG_MORE 플래그와 함께 AF_ALG 소켓을 통해 작은 페이로드 청크를 전송하여 커널에 더 많은 데이터가 올 것임을 알립니다.splice()합니다.익스플로잇은 전체 대상 바이너리의 캐시된 페이지가 사용자 정의 페이로드로 덮어쓰여질 때까지 각 4바이트 윈도우에 대해 이 과정을 반복합니다.
파일에 대한 쓰기 권한은 필요하지 않습니다. 디스크의 파일은 변경되지 않으며, 메모리 내 페이지 캐시만 손상됩니다.
컨테이너 런타임은 오버레이 파일 시스템을 사용합니다. 두 컨테이너가 동일한 이미지 레이어를 공유할 때, 커널은 동일한 페이지 캐시 페이지에서 파일 읽기를 제공합니다.
공격자는 대상 권한 있는 DaemonSet과 동일한 기본 이미지를 FROM하여 PoC 이미지를 빌드합니다. 두 컨테이너가 동일한 오버레이 하위 디렉터리를 공유하기 때문에 공유 레이어의 바이너리는 동일한 페이지 캐시 페이지에 매핑됩니다.
권한 없는 PoC 컨테이너가 바이너리의 페이지 캐시를 손상시키면, 손상은 즉시 동일한 노드의 권한 있는 컨테이너에 표시됩니다 — 컨테이너 간 통신은 전혀 없습니다.
권한 있는 DaemonSet이 다음에 손상된 바이너리를 실행할 때(정상 작동 주기를 통해), 커널은 손상된 페이지 캐시 페이지를 로드합니다. 공격자의 페이로드는 DaemonSet의 전체 권한으로 실행되며, 여기에는 다음이 포함될 수 있습니다:
이 PoC의 페이로드(payload/payload.c)는 단순히 호스트 루트 파일 시스템을 마운트하고 노드 수준 코드 실행의 증명으로 마커 파일을 /root/res에 기록합니다.
┌──────────────────────────┐ ┌──────────────────────────┐
│ PoC 컨테이너 │ │ 권한 있는 DaemonSet │
│ (권한 없음) │ │ (예: kube-proxy, │
│ │ │ 모니터링 에이전트 등) │
│ 1. 대상 바이너리 열기 │ │ │
│ (읽기 전용) │ │ │
│ │ │ │
│ 2. AF_ALG splice 경합 │ │ │
│ 조건으로 페이지 캐시 │ │ │
│ 손상 │ │ │
│ │ │ │ │
└──────────┼───────────────┘ └──────────────────────────┘
│ │
▼ │
┌─────────────────────┐ │
│ 커널 페이지 캐시 │ │
│ │◄────────────────────┘
│ 공유 레이어 바이너리 │ 3. DaemonSet이 손상된
│ (손상됨) │ 바이너리 실행
│ 공격자의 페이로드 │ → 손상된 페이지 로드
│ 바이트 포함 │ → 페이로드가 DaemonSet의
└─────────────────────┘ 권한으로 실행됨
PoC는 다음 관리형 Kubernetes 플랫폼에서 성공적으로 검증되었습니다:
| 속성 | 값 |
|---|---|
| 플랫폼 | Alibaba Cloud Container Service for Kubernetes (ACK) |
| Kubernetes | v1.35.2 |
| 노드 커널 | 6.6.88-4.2.alnx4.x86_64 |
| kube-proxy | registry-cn-*.ack.aliyuncs.com/acs/kube-proxy:v1.35.2-aliyun.1 |
| 기본 이미지 | registry.k8s.io/kube-proxy:v1.35.2 (업스트림) |
| 루트 장치 | /dev/vda3 (ext4) |

| 속성 | 값 |
|---|---|
| 플랫폼 | Amazon Elastic Kubernetes Service (EKS) |
| Kubernetes | v1.35.4 |
| 노드 커널 | 6.12.79-101.147.amzn2023.x86_64 |
| kube-proxy | ***.dkr.ecr.***.amazonaws.com.cn/eks/kube-proxy:v1.35.3-eksbuild.2 |
| 기본 이미지 | public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-iptables:2026-03-11-1773190710.2023 |
| 루트 장치 | /dev/nvme0n1p1 (xfs) |

| 속성 | 값 |
|---|---|
| 플랫폼 | Google Kubernetes Engine (GKE) |
| Kubernetes | v1.35.3-gke.1234000 |
| 노드 OS | Container-Optimized OS (COS) 125, BUILD_ID 19216.220.72 |
| 노드 커널 | 6.12.68+ x86_64 |
| kube-proxy | us-central1-artifactregistry.gcr.io/gke-release/gke-release/kube-proxy:v1.35.3-gke.1234000 |
| 기본 이미지 | kube-proxy와 동일 (GKE 제공업체 관리 Artifact Registry 이미지) |
| 루트 장치 | /dev/dm-0 (ext2, 읽기 전용); /dev/sda1 (ext4, 쓰기 가능한 상태 파티션) |
| 마커 경로 | /mnt/stateful_partition/copyfail-res |

세 경우 모두, 권한 없는 PoC 파드가 호스트 파일 시스템에 [*] success 마커 파일을 성공적으로 기록했습니다 — 이는 권한 있는 kube-proxy DaemonSet을 통한 노드 수준 코드 실행을 증명합니다.
전체 워크스루(이미지 레이어 분석, 빌드 단계, 배포)는 다음을 참조하세요:
이 PoC는 가장 일반적인 권한 있는 DaemonSet 중 하나인 kube-proxy를 대상으로 사용합니다. 세 가지 변형이 제공됩니다:
FROM registry.k8s.io/kube-proxy:v1.35.2로 빌드됨 (Dockerfile 참조)FROM public.ecr.aws/eks-distro-build-tooling/eks-distro-minimal-base-iptables:2026-03-11-1773190710.2023로 빌드됨 (Dockerfile.eks 참조)FROM us-central1-artifactregistry.gcr.io/gke-release/gke-release/kube-proxy:v1.35.3-gke.1234000로 빌드됨 (Dockerfile.gke 참조)모든 변형은 /usr/sbin/ipset, /usr/sbin/nft, /usr/sbin/xtables-legacy-multi, /usr/sbin/xtables-nft-multi와 같은 바이너리를 손상시킵니다.
중요한 주의 사항:
ipset을 호출합니다. 기본 모드(iptables)는 ipset을 사용하지 않습니다. ipvs 폐기 계획은 kubernetes/enhancements#5495를 참조하세요.ipset, nft, xtables-legacy-multi, xtables-nft-multi)를 대상으로 하여 다양한 프록시 모드를 포괄하지만, 호출 여부는 클러스터 구성에 따라 다릅니다.