다중 테넌트 Linux 서버를 운영 중이라면 다음 재부팅까지만 Copy Fail 취약점을 해결할 시간이 있습니다. Microsoft Threat Intelligence는 2026년 5월 1일 CVE-2026-31431을 공개했습니다(Theori의 발견과 Xint의 732바이트 root 권한 상승 코드에 대한 크레딧). CVSS 점수는 7.8(높음)이며, CERT-EU는 같은 날 조언 2026-005를 발표했습니다.

Copy Fail을 다르게 만드는 것은 RuntimeDefault seccomp를 기본적으로 우회하는 첫 번째 주요 Linux 권한 상승 취약점이라는 점입니다. Pod Security Standards Restricted가 적용된 "안전한" Kubernetes 파드도 영향을 받습니다. 지금 이 글을 읽고 행동하세요.

TL;DR: 다음 60분 동안 해야 할 일

다른 것은 읽지 않더라도 지금 바로 다음 6가지를 하세요:

  • 프로덕션 배포를 일시 중지하고 /var/log/auth.log와 kubectl get events -A를 스냅샷합니다(작업 시작 전).
  • 모든 노드에서 uname -r을 실행합니다. 배포판의 패치된 커널 버전보다 낮으면 취약합니다.
  • algif_aead를 즉시 비활성화합니다: echo "blacklist algif_aead" > /etc/modprobe.d/copy-fail.conf && rmmod algif_aead
  • 배포판의 Copy Fail 패치를 적용하고 재부팅합니다(Ubuntu USN, AlmaLinux ALSA, SUSE SU).
  • Kubernetes 노드마다 socket(AF_ALG, ...) 호출을 거부하는 Localhost seccomp 프로필을 배포하고 kubelet을 다시 로드합니다.
  • 지난 30일간의 auth.log와 EDR에서 예상치 못한 socket(AF_ALG) 시스템콜과 새로운 setuid 바이너리를 감사합니다.

전체 설명(명령어, 배포판별 패치, K8s seccomp 프로필)은 아래에 있습니다.

실제 일어난 일: CVE-2026-31431 내부 동작

CVE-2026-31431("Copy Fail")은 algif_aead의 Linux 커널 권한 상승 결함입니다. AF_ALG 소켓을 열고 조작된 authenc-esn 요청으로 splice()를 트리거하면, 권한이 없는 사용자가 페이지 캐시에 4바이트를 기록하여 setuid 바이너리를 손상시키고 root 권한을 획득합니다. CVSS는 7.8(높음)입니다.

근본 원인은 2017년 algif_aead의 제자리 암호화 최적화로 거슬러 올라갑니다. 이는 커널 암호화 기본 요소를 사용자 공간에 노출하는 AF_ALG 소켓 인터페이스입니다. Xint의 익스플로잇이 올바른 authenc-esn 요청을 소켓으로 보내고 splice()를 통해 파이프할 때, 최적화 코드가 4바이트를 의도한 버퍼 너머 페이지 캐시로 기록합니다. 올바른 오프셋을 선택하면 /usr/bin/sudo나 다른 setuid 바이너리를 디스크에서 다시 쓸 수 있습니다. 메인라인 수정은 커밋 a664bf3d603d로 병합되었습니다.

익스플로잇은 매우 작습니다. Xint는 732바이트의 작동하는 PoC를 공개했으며, 트리거 표면은 컨테이너 내부에서도 접근 가능합니다. 이 부분이 당신의 마음을 졸아야 하는 이유입니다.

"Dirty Pipe vs Copy Fail"이 익숙하게 들린다면 비교는 타당합니다. 둘 다 임의의 페이지 캐시 기록을 생성하는 Linux 커널 권한 상승 취약점입니다. Dirty Pipe(CVE-2022-0847)는 파이프로의 splice()를 남용했고, Copy Fail은 algif_aead 소켓으로의 splice()를 남용합니다. 둘 다 표준 컨테이너 seccomp 기본값을 우회합니다. Copy Fail의 특이한 점은 AF_ALG 경로가 RuntimeDefault를 적용한 Pod Security Standards Restricted 내에서 도달 가능하다는 것입니다. 같은 대응 패턴이지만 다른 커널 표면입니다. 우리는 Vercel 위반 이후 대응 패턴을 다루었고, 구조는 여기에 깔끔하게 적용됩니다.

영향을 받고 있습니까? 5분 내 판단하기

uname -r을 실행하고 배포판의 패치된 커널과 비교합니다: Ubuntu 6.19.12, AlmaLinux/RHEL 7.0, SUSE 6.18.22. 그 다음 lsmod | grep algif_aead를 실행합니다. 모듈이 로드되어 있고 커널이 패치된 버전보다 오래되었으면 취약합니다. 모듈이 없지만 /etc/modprobe.d에서 블랙리스트로 지정하지 않았으면 여전히 취약합니다.

운영 중인 모든 Linux 호스트에서 다음 4가지 명령어를 순서대로 실행합니다:

솔직한 참고: lsmod가 algif_aead에 대해 아무것도 반환하지 않으면 안전하지 않습니다. 권한이 없는 사용자는 대부분의 배포판에서 직접 modprobe algif_aead를 실행할 수 있습니다. kmod가 자동 로드 대상 모듈에 대해 권한으로 제한하지 않기 때문입니다. "모듈이 언로드됨"은 TL;DR 3단계에서 블랙리스트 파일을 추가할 때까지 "모듈에 접근할 수 없음"이 아닙니다.

우리는 Ubuntu 24.04 LTS와 Kubernetes 1.30(containerd 1.7)에서 algif_aead 제거를 테스트했습니다. 모듈은 /etc/modprobe.d/copy-fail.conf를 추가할 때까지 셸 접근 권한이 있는 모든 사용자에 대해 다시 로드되었습니다. 블랙리스트를 필수 사항으로 취급하세요. 백업 계획이 아닙니다.

AI/ML 및 Kubernetes 스택이 더 높은 위험에 처한 이유

자체 호스팅 AI 워크로드는 신뢰할 수 없는 코드를 자주 실행하기 때문에 불균형적으로 노출됩니다: HuggingFace 아티팩트, MCP 서버, 에이전트 실행기, 사용자 데이터의 미세 조정 작업, 모델 컨테이너를 구축하는 CI/CD 러너. Pod Security Standards Restricted는 기본적으로 socket(AF_ALG, ...)을 차단하지 않으므로, 손상된 추론 파드는 호스트 커널을 깰 수 있습니다. Juliet.sh는 제어된 K8s 테스트에서 이를 직접 확인했습니다.

이 문제가 가장 심각하게 타격을 주는 5가지 장소:

  • vLLM, sglang, Ollama, Ray Serve 같은 자체 호스팅 추론 서버. 자주 다중 테넌트이고, 사용자가 제공한 LoRA 어댑터나 도구 코드를 자주 실행합니다. 우리의 vLLM vs sglang 비교는 운영 구조를 다룹니다. 둘 다 RuntimeDefault를 사용하는 기본 containerd 파드에서 기꺼이 실행됩니다.

  • MCP 서버. 타사 플러그인이 셸 명령을 실행하고, 사용자 입력을 파싱하고, 모델 자체와 같은 파드 내에서 실행될 수 있습니다. 에이전트 런타임을 구축한 누구나 상태를 유지하는 방법을 알고 있으면 신뢰 경계가 얼마나 얇은지 압니다.

  • 임의의 HuggingFace 아티팩트를 가져오고 신뢰할 수 없는 소스에서 pip install을 실행하는 ML 이미지를 구축하는 CI/CD 러너. 모두 러너의 UID로 실행됩니다.

  • 정의에 따라 에이전트 코드가 런타임에 사용자 제어를 받는 에이전트 플랫폼. 에이전트 배포 플랫폼을 운영하면 모든 플러그인과 도구 확장은 범위 내입니다.

  • GPU 노드. 일반적으로 강력하고 다중 테넌트이며, 종종 CUDA/드라이버 접근을 위해 보안 프로필이 완화되어 실행됩니다. 또한 당신이 가진 가장 높은 비용의 머신이기도 합니다. 공유 GPU 리그에서 로컬로 LLM을 실행하는 팀이 명백한 대상입니다.

구체적인 예: 사용자가 requirements.txt를 포함하는 LoRA 어댑터를 업로드합니다. pip install은 추론 컨테이너의 UID로 실행됩니다. RuntimeDefault를 사용하는 PSS Restricted에서도 이 컨테이너는 socket(AF_ALG, ...)을 호출하고 Copy Fail을 트리거할 수 있습니다. 호스트를 잃었습니다. 해당 노드를 공유하는 다른 모든 파드가 이제 폭발 반경 내에 있습니다.

60분 긴급 대응 플레이북

5가지 단계를 순서대로 작업하여 60분 안에 Copy Fail을 패치하세요: Freeze(5분 — 자동 배포 일시 중지, 로그 스냅샷), Detect(10분 — 노드마다 uname -r과 lsmod), Mitigate(15분 — modprobe 블랙리스트 및 seccomp 프로필), Patch(20분 — 배포판 커널 업데이트 및 롤링 재부팅), Verify(10분 — lsmod가 비어 있는지 확인하고 uname -r이 패치된 버전과 일치하는지 확인).

목표는 1시간 이내에 패치되고, 검증되고, 서비스로 돌아가는 것입니다. 5가지 타이트한 단계로 나누었습니다.

Phase 1 — Freeze (0:00–0:05)

자동 배포를 일시 중지하고, 로그를 스냅샷하고, 현재 상태를 기록할 때까지 apt upgrade / dnf update를 보류합니다.

Phase 2 — Detect (0:05–0:15)

이전 섹션의 4가지 명령어 판단을 모든 호스트에서 실행합니다. Kubernetes의 경우 이 한 줄 명령어는 모든 노드에서 uname -r을 실행합니다:

Sysdig가 게시한 Falco 규칙(Unexpected AF_ALG Socket Creation)도 여기에 배포할 가치가 있습니다. Phase 3이 끝난 후 뭔가 여전히 시도 중이면 즉시 트리거됩니다.

Phase 3 — Mitigate (0:15–0:30)

algif_aead를 비활성화합니다. 이것이 algif_aead 비활성화 순서입니다. 재부팅 없이 몇 초 안에 적용됩니다.

또한 이제 copy fail seccomp 프로필을 H2 #7에서 kubelet seccomp 디렉터리로 배포합니다. Phase 4까지 기다리지 마세요.

Phase 4 — Patch (0:30–0:50)

배포판 패치를 적용합니다. 아래 배포판별 표는 배포판별 한 줄 명령어를 포함합니다. Kubernetes의 경우 drain-cordon-uncordon이 안전한 패턴입니다:

테스트 실행에서 modprobe + rmmod 순서는 노드당 ~8초가 걸렸습니다. 커널 설치 + 재부팅은 배포판에 따라 노드당 3~5분이 걸렸습니다. 전체 플릿에 걸쳐 예산을 책정하세요.

Phase 5 — Verify (0:50–1:00)

판단을 다시 실행합니다. lsmod | grep algif_aead가 비어 있는지, uname -r이 패치된 버전과 일치하는지, kubectl get nodes가 새로운 커널에서 모든 노드가 Ready인지 확인합니다.

...

출처 바로가기