요약(Executive Summary)> 2026년 4월 29일, 보안 연구기업 Xint(Xint Code Research Team)가 리눅스 커널의 암호화 서브시스템에서 발견한 신종 권한상승 취약점CVE-2026-31431, 일명 "Copy Fail"을 공개했다. 이 취약점은 비특권 로컬 사용자가 단 732바이트짜리 파이썬 스크립트만으로 우분투, Amazon Linux, RHEL, SUSE 등 사실상 모든 주요 리눅스 배포판에서 루트(root) 권한을 획득할 수 있게 만든다. 더욱 심각한 것은 이 결함이 2017년부터 약 9년간 모든 메이저 배포판에 조용히 잠재해 있었다는 점이며, 컨테이너 경계까지 무력화시키는 쿠버네티스 노드 탈출(container escape) 1차 프리미티브로도 활용된다는 사실이다.
1. 취약점 한눈에 보기
| 항목 | 내용 |
|---|---|
| CVE 번호 | CVE-2026-31431 |
| 명칭 | Copy Fail |
| 발견자 | Theori 소속 이태양(Taeyang Lee) 연구원 + Xint Code(AI 보조 분석) |
| 공개일 | 2026년 4월 29일 |
| 영향 범위 | 2017년 이후 출시된 사실상 모든 리눅스 배포판 (Ubuntu 24.04, Amazon Linux 2023, RHEL 10.1, SUSE 16 등 직접 검증) |
| 영향받는 커널 라인 | 6.12, 6.17, 6.18 등 (2017년 이후 모든 커널 포함) |
| 공격 벡터 | 로컬 비특권 사용자 → root |
| 부가 영향 | 컨테이너/쿠버네티스 노드 탈출(Part 2 공개 예정) |
| 익스플로잇 크기 | 732바이트, 순수 Python 표준 라이브러리만 사용 |
2. 왜 "Copy Fail"이 위험한가 — Dirty Cow, Dirty Pipe와의 결정적 차이
리눅스 커널 권한상승 취약점은 새로운 이야기가 아니다. 2016년의 Dirty Cow(CVE-2016-5195), 2022년의 Dirty Pipe(CVE-2022-0847)가 대표적이다. 그러나 Copy Fail은 이들과 본질적으로 다른 위험성을 가진다.
(1) 경쟁 조건(race condition)이 없다.Dirty Cow는 VM 서브시스템의 copy-on-write 경로에서 race를 이겨야 했으며, 다회 시도와 시스템 크래시를 동반했다. Copy Fail은단일 직선(straight-line) 로직 결함으로, 재시도나 타이밍 운에 의존하지 않는 결정론적(deterministic) 공격이다.
(2) 이식성(portability)이 압도적이다.배포판별 오프셋 보정, 재컴파일, 버전 체크가 일체 불필요하다.동일한 스크립트 한 본이 Ubuntu, Amazon Linux, RHEL, SUSE에서 그대로 동작한다.
(3) 극도로 작고 가볍다.표준 라이브러리(os, socket, zlib)만 사용하는 Python 3.10+ 스크립트로, 컴파일된 페이로드도, 외부 의존성 설치도 필요 없다.(4) 스텔스성(stealth) — 디스크에는 흔적이 남지 않는다.변조는 페이지 캐시(page cache)의 인메모리 사본에만 발생한다. 커널이 해당 페이지를 dirty로 표시하지 않기 때문에디스크 상의 파일과 체크섬은 그대로다. AIDE, Tripwire, Wazuh 같은 온디스크 무결성 검증 도구는 이 변조를 절대 탐지하지 못한다.그러나 시스템이 파일을 읽을 때 실제로 참조하는 것은 페이지 캐시이므로, 변조된 버전은 시스템 전역에 즉시 적용된다.(5) 컨테이너 격리를 무력화한다.페이지 캐시는 호스트와 모든 컨테이너가 공유한다. 즉, 컨테이너 내부의 비특권 사용자가 호스트의 setuid 바이너리를 변조할 수 있다는 의미이며, 이는 곧쿠버네티스 노드 침해(node compromise) 1차 프리미티브가 된다.
3. 기술적 근본 원인 — "선의의 최적화"가 만든 9년짜리 시한폭탄
이 취약점은 단일 결함이 아니라, 세 가지 정상적인 설계 결정의 교차점에서 발생했다.
(1) AF_ALG: 비특권 사용자에게 열린 커널 암호화 인터페이스
AF_ALG는 사용자 공간이 커널 암호화 서브시스템을 직접 호출할 수 있도록 만든 소켓 타입이다. 별도 권한이 필요하지 않으며, 사용자는 임의의 AEAD 알고리즘에 데이터를 던져 넣을 수 있다.
(2) splice(): 페이지 캐시 페이지를 "참조로" 전달
splice()는 복사 없이 파일 디스크립터와 파이프 사이에서 데이터를 이동시킨다. 이때 데이터는 복제되지 않고 페이지 캐시 페이지의 참조가 그대로 전달된다. 즉, 파일을 splice → pipe → AF_ALG 소켓으로 흘려 넣으면, 암호화 서브시스템의 입력 scatterlist가 해당 파일의 실제 커널 캐시 페이지를 직접 가리키게 된다.
(3) 2017년의 In-place 최적화 — 운명의 한 줄
2017년, algif_aead.c에 성능 최적화를 위한 in-place 연산이 도입되었다(commit 72548b093ee3). AAD와 ciphertext는 사용자 버퍼로 복사하되, 인증 태그(authentication tag) 영역은 sg_chain()으로 원본 페이지 캐시를 그대로 출력 scatterlist에 연결해 두는 구조였다. 그리고 req->src = req->dst로 설정함으로써 페이지 캐시 페이지가 "쓰기 가능한 목적지" scatterlist 안에 들어가 버린 것이다.
req->src ----+
v
req->dst --> [ AAD || CT ] --> [ Tag (페이지 캐시 페이지!) ]
| RX 버퍼 | | TX SGL에서 chain |
| (사용자 메모리) | (대상 파일의 페이지 캐시)
(4) 방아쇠 — authencesn의 "스크래치 쓰기"
취약점의 마지막 조각은 IPsec ESN(Extended Sequence Number)을 위한 AEAD 래퍼인 authencesn이다. 이 알고리즘은 ESN 바이트를 재배열하는 과정에서 호출자의 목적지 버퍼를 임시 메모장(scratch space)으로 사용한다. 문제는 마지막 한 줄:
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);
이 호출은 AEAD 태그의 경계를 넘어 4바이트를 기록한다. 일반적인 환경에서는 이 영역이 호출자가 소유한 버퍼이므로 무해하지만, In-place AF_ALG 경로에서는 그 4바이트가 chain된 페이지 캐시 페이지, 즉 시스템상의 모든 사용자가 읽는 실제 파일 콘텐츠에 직접 새겨진다.
공격자가 통제 가능한 세 가지 변수
- 어떤 파일을 — 현재 사용자가 읽을 수 있는 모든 파일 (예:
/usr/bin/su같은 setuid 바이너리) - 어느 오프셋에 — splice 오프셋, 길이, assoclen 조합으로 정밀 제어
- 어떤 값을 — sendmsg AAD의 4-7바이트가 그대로 기록 값
요약하면, 공격자가 임의로 선택한 파일의 임의 위치에, 임의의 4바이트를 결정론적으로 쓸 수 있는 원시(primitive)가 비특권 사용자에게 열려 있었다는 뜻이다.
4. 익스플로잇 시나리오 — 4바이트가 root가 되기까지
기본 익스플로잇 표적은 /usr/bin/su 다. 모든 메이저 배포판에 setuid-root로 설치되어 있는 바이너리다.
- 소켓 설정: AF_ALG 소켓을 열고
authencesn(hmac(sha256),cbc(aes))에 바인딩 - 쓰기 구성: 셸코드 페이로드를 4바이트 단위로 분할, 각 청크마다 sendmsg + splice 쌍 구성
- 트리거:
recv()호출 → 커널이authencesn복호화 수행 → HMAC 검증 실패 → 그러나 4바이트는 이미 페이지 캐시에 기록됨 - 실행: 모든 청크 기록 후
execve("/usr/bin/su")호출 → 커널이 페이지 캐시에서 변조된 바이너리 로드 → 주입된 셸코드가 UID 0(root)으로 실행
핵심 코드 윤곽은 다음과 같다.
import os, socket
a = socket.socket(38, 5, 0) # AF_ALG, SOCK_SEQPACKET
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
# ... 키 설정 및 request 소켓 accept ...
u.sendmsg([b"A"*4 + payload_chunk], [cmsg_headers], MSG_MORE)
os.splice(target_fd, pipe_wr, offset)
os.splice(pipe_rd, alg_fd, offset)
u.recv(...) # 복호화 트리거 → 페이지 캐시 쓰기 발생
전체 익스플로잇이 732바이트라는 사실은 그 자체가 위협이다. 이 정도 크기는 한 줄짜리 파이프라인, 패스트북(pastebook) 한 토막, 심지어 단일 트윗에도 충분히 들어간다. 침투 후 흔적을 남기지 않고 즉시 휘발될 수 있는 규모다.
5. 어떻게 9년간 묻혀 있었나 — 세 결정의 우연한 교차점
이 결함은 누구 한 사람의 실수가 아니다. 시간 순으로 보면 다음과 같다.
| 연도 | 사건 | 당시의 위험성 |
|---|---|---|
| 2011 | authencesn이 IPsec ESN 지원을 위해 커널에 추가됨 (commit a5079d084f8b). 처음부터 목적지 scatterlist를 스크래치 공간으로 사용. |
무해. AAD가 별도 scatterlist에 있었고, 호출자도 커널 내부 xfrm 계층뿐이었음. |
| 2015 | AF_ALG에 AEAD 지원이 추가됨(algif_aead.c). 같은 해 authencesn이 새 AEAD 인터페이스로 전환되며 assoclen + cryptlen 오프셋에 쓰는 구조가 도입됨 (commit 104880a6b470). |
여전히 무해. AF_ALG가 out-of-place로 동작하고 있어, 페이지 캐시 페이지는 src(읽기 전용)에만 위치. |
| 2017 | algif_aead.c에 in-place 최적화가 적용됨 (commit 72548b093ee3).req->src = req->dst로 통합되며 페이지 캐시 페이지가쓰기 가능한 destination scatterlist에 chain됨. |
이 시점부터 모든 메이저 리눅스 배포판에 Copy Fail이 잠재. |
각 결정은 그 자체로는 합리적이었다. 그러나 세 결정이 만나는 지점에서 누구도 연결 고리를 보지 못한 채 9년이 흘렀다. 이는 현대 커널 보안의 가장 어려운 문제 — "isolated review가 통과시킨 변경들의 누적 상호작용" — 을 정확히 보여주는 사례다.
6. 영향 범위와 심각도 평가
Xint이 직접 검증한 환경
| 배포판 | 커널 버전 |
|---|---|
| Ubuntu 24.04 LTS | 6.17.0-1007-aws |
| Amazon Linux 2023 | 6.18.8-9.213.amzn2023 |
| RHEL 10.1 | 6.12.0-124.45.1.el10_1 |
| SUSE 16 | 6.12.0-160000.9-default |
잠재적 영향 영역
- 퍼블릭 클라우드 인스턴스: AWS EC2(특히 Amazon Linux), Azure, GCP 모두 영향
- 온프레미스 엔터프라이즈 서버: RHEL, SUSE, Ubuntu Server 운영 환경 대부분
- 컨테이너/쿠버네티스: 페이지 캐시가 호스트와 공유되므로 컨테이너 내부에서 호스트 setuid 바이너리 변조 가능 → 노드 전체 침해-CI/CD 러너: GitHub Actions self-hosted runner, GitLab runner, Jenkins worker 등 비신뢰 코드를 실행하는 모든 환경
- 공유 호스팅·VDI 환경: 일반 사용자 셸 권한만 있어도 즉시 root 탈취
특히 쿠버네티스 환경에서의 영향은 다음 공개 예정인 Part 2에서 상세히 다뤄질 예정이며, "Pod에서 호스트로(From Pod to Host)"라는 제목 그대로 모든 주요 클라우드 매니지드 쿠버네티스 플랫폼이 탈출 대상이라고 Xint는 예고했다.
7. 패치 분석과 대응 방안
공식 패치
패치 커밋(a664bf3d603d)은 2017년의 in-place 최적화를 전면 되돌려(revert) out-of-place 동작으로 회귀시킨다. 즉, 페이지 캐시 페이지가 더 이상 쓰기 가능한 destination scatterlist에 chain되지 않는다.
// 수정 전: src와 dst가 동일 scatterlist (in-place)
aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src,
areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv);
// 수정 후: src는 TX SGL, dst는 RX SGL (out-of-place)
aead_request_set_crypt(&areq->cra_u.aead_req, tsgl_src,
areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv);
커밋 메시지는 명료하다 — "algif_aead에서 source와 destination이 서로 다른 매핑에서 오는 이상, in-place 동작은 어떠한 이점도 없다."
권장 대응 절차
(1) 즉시 — 커널 패키지 업데이트각 배포판 벤더(Ubuntu, Amazon, Red Hat, SUSE 등)가 배포하는 커널 보안 업데이트를 정상 패치 채널로 즉시 적용한다.(2) 패치 전 임시 완화 — algif_aead 모듈 차단
패치 적용이 즉시 어려운 환경에서는 다음과 같이 모듈 로딩을 차단한다.
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
(3) 컨테이너 보안 강화seccomp 프로파일에 socket(AF_ALG, ...) 차단을 추가한다. Docker 기본 seccomp는 일부 보호를 제공하지만, 커스텀 프로파일을 사용하는 경우 명시적으로 차단해야 한다.(4) 무결성 모니터링의 한계 인지
중요: 디스크 기반 무결성 검사(AIDE, Tripwire 등)는 이 공격을 탐지할 수 없다. 따라서 메모리 기반 탐지(eBPF 기반 행위 모니터링, AF_ALG 비정상 사용 탐지)를 보완 수단으로 도입하는 것이 권장된다.
(5) 이상 행위 탐지 룰 추가
- 비특권 프로세스의
authencesn사용 - 짧은 시간 내 다수의 splice → AF_ALG 패턴
- setuid 바이너리 실행 직전 비정상 AF_ALG 활동
8. 책임 있는 공개(Responsible Disclosure) 타임라인
| 일자 | 사건 |
|---|---|
| 2026-03-23 | 리눅스 커널 보안팀에 취약점 보고 |
| 2026-03-24 | 최초 수신 확인 |
| 2026-03-25 | 패치 제안 및 검토 |
| 2026-04-01 | 메인라인 커널에 패치 커밋 |
| 2026-04-22 | CVE-2026-31431 할당 |
| 2026-04-29 | 공개 (Xint 블로그 게시) |
보고에서 공개까지 약 5주. 매우 빠른 대응 사이클이며, 이는 결함의 근본 원인이 명확한 단일 커밋으로 좁혀졌고 패치가 기존 코드의 단순 revert였다는 점에 기인한다.
9. 시사점 — AI 보조 취약점 발굴 시대의 개막
이번 발굴 과정에는 또 하나의 주목할 만한 요소가 있다. 바로 AI 기반 취약점 분석 도구 "Xint Code"가 발굴 과정에 결정적으로 활용되었다는 점이다.
연구자 이태양은 이전 kernelCTF 작업을 통해 *"AF_ALG + splice 조합이 비특권 사용자 공간에서 페이지 캐시 페이지를 암호화 서브시스템에 직접 전달하는 경로를 만들 수 있다"*는 핵심 통찰을 갖고 있었다. 이 통찰을 운영자 프롬프트(operator prompt)로 Xint Code에 입력했고, 약 1시간 만에 도구는 crypto/ 서브시스템 전체에서 Copy Fail을 최고 심각도 결과로 식별해 냈다.
이는 보안 연구 패러다임의 변화를 시사한다.
- 인간 연구자: 공격면(attack surface) 정의, 비자명한 invariant 식별, 도메인 통찰 제공
- AI 도구: 정의된 공격면을 따라 광범위하고 일관된 코드 경로 추적 및 패턴 매칭
같은 스캔에서 추가적인 고심각도 권한상승 취약점들이 더 발견되었으며 책임 공개 절차가 진행 중이라는 Xint의 언급은, 향후 수개월 내 유사한 등급의 결함이 연달아 공개될 가능성을 예고한다.
10. 결론 — 보안 책임자가 지금 당장 해야 할 일
Copy Fail은 단순한 또 하나의 LPE(Local Privilege Escalation) 취약점이 아니다. 다음 세 가지 측면에서 보안 책임자에게 실질적인 행동을 요구한다.
첫째, 모든 리눅스 자산의 패치 우선순위를 즉시 재조정해야 한다.일반적인 LPE는 "원격 진입점이 별도로 있어야 위험"하다고 평가되어 후순위로 밀리곤 한다. 그러나 Copy Fail은 (1) 컨테이너 탈출까지 가능하고 (2) 디스크 무결성 검증으로 탐지되지 않으며 (3) 익스플로잇이 트위터 한 줄에 들어갈 만큼 작다.패치 우선순위는 RCE급으로 취급되어야 한다.
둘째, 컨테이너 보안 모델에 대한 가정을 재검토해야 한다."컨테이너 격리 + 비특권 사용자"라는 이중 방어가 작동하지 않는 케이스가 다시 한번 입증되었다. 페이지 캐시는 커널 자원이며 컨테이너 경계를 알지 못한다.공유 커널 위에서 동작하는 컨테이너의 본질적 한계를 다시 인식하고, 신뢰 경계가 중요한 워크로드는 gVisor·Kata Containers·Firecracker 같은 강한 격리 옵션을 검토해야 한다.
셋째, AI 보조 취약점 발굴이 만들어 낼 "공개 가속화"에 대비해야 한다.Xint Code가 한 번의 스캔에서 다수의 고심각도 결함을 추가로 발견했다는 점, 그리고 동일한 도구를 다른 연구팀과 공격자들도 곧 사용하게 될 것이라는 점은,앞으로 메이저 커널·런타임·라이브러리에서 동등한 등급의 결함이 더 짧은 주기로 공개될 가능성을 의미한다. 정기 패치 사이클(월 1회 등)에 안주하는 조직은 갈수록 노출 윈도우가 커진다. 무중단 패치 자동화와 가상 패치(virtual patching) 역량 확보가 더 이상 옵션이 아닌 필수 영역으로 이동하고 있다.732바이트. 단지 그 정도의 코드가 9년간 잠들어 있던 결함을 깨워, 전 세계 리눅스 인프라의 신뢰 경계를 무너뜨릴 수 있다는 사실은,현대 커널 보안이 "단일 결함의 심각도"가 아니라 "결정의 누적 상호작용"의 시대로 들어섰음을 분명히 보여준다.
참고 자료
- 원문 공개 글: Xint, "Copy Fail: 732 Bytes to Root on Every Major Linux Distribution" (2026-04-29)
- 패치 커밋: torvalds/linux a664bf3d603d
- 도입 커밋(취약 시점): torvalds/linux 72548b093ee3 (2017)
- CVE-2026-31431
- 후속 공개 예정: Part 2 — "From Pod to Host: Kubernetes Container Escape via Copy Fail"
본 칼럼은 공개된 기술 보고서를 바탕으로 작성된 분석 자료이며, 익스플로잇의 구체적 코드는 보안상의 이유로 의도적으로 일부만 발췌하였습니다.