
Dirty Frag에 대한 보고서입니다. 이는 권한이 없는 사용자가 루트 액세스 권한을 획득할 수 있게 하는 Linux 로컬 권한 상승(LPE) 취약점 체인입니다.
Linux 커널 로컬 권한 상승 체인에 대한 익스플로잇 재현 및 탐지 연구소입니다.
상태: 검증 완료. 저는 연구소 환경(커널 6.18.9+kali-amd64)에서 재현, 파일리스 검증, 그리고 syscall 수준 탐지를 완료했습니다. 이 문서는 연구소 로그입니다. 아래의 모든 주장은 재현 실행 중 관찰된 것입니다. 스크린샷과 아티팩트는 VM에서 캡처한 실제 자료입니다.
Dirty Frag는 Linux 커널의 두 가지 결정적 로직 버그를 결합합니다. 이러한 버그로 인해 권한이 없는 로컬 사용자가 읽기 전용 파일(예: /usr/bin/su)의 페이지 캐시를 덮어쓰고 루트 셸을 얻을 수 있습니다:
| 변종 | CVE | 싱크 | 트리거 경로 | 권한 없는 userns 필요 |
|---|---|---|---|---|
| xfrm‑ESP 페이지‑캐시 쓰기 | CVE‑2026‑43284 | esp_input()의 crypto_authenc_esn_decrypt() | UDP‑encap을 사용한 socket(AF_INET), 이후 xfrm_input() | 예 (CAP_NET_ADMIN) |
| RxRPC 페이지‑캐시 쓰기 | CVE‑2026‑43500 | rxkad_verify_packet_1() (pcbc(fcrypt)) | socket(AF_RXRPC) | 아니요 |
두 변종 모두 Dirty Pipe 및 Copy Fail과 동일한 루트 패턴을 사용합니다. splice(2) syscall은 파일의 페이지-캐시 페이지에 대한 참조를 송신 측 sk_buff의 frag 슬롯에 배치합니다. 공격자는 이 파일을 읽기만 할 수 있습니다. 수신 측 커널 코드는 해당 frag 위에서 제자리 암호화 STORE를 수행합니다. 이는 RAM의 페이지 캐시를 변형시킵니다. 디스크 쓰기가 발생하지 않으므로 파일 무결성 모니터링(AIDE, Tripwire)은 이를 감지할 수 없습니다. 공격은 결정적입니다. 경쟁 조건 창이 없으며 실패 시 커널 패닉도 없습니다.
cac2661c53f3(2017‑01)부터 f4c50a4034e6(2026‑05‑05 패치)까지2dc334f1a63a(2023‑06)부터 aa54b1d27fe0(2026‑05‑10 패치)까지CVE-2026-43284 = 8.8 (높음), CVE-2026-43500 = 7.8 (높음)Dirty Frag는 파일리스 LPE입니다. 디스크의 파일이 아닌 메모리 내 페이지 캐시를 손상시킵니다. 기존 파일 무결성 모니터링은 이를 감지할 수 없습니다. 탐지는 syscall 계층에서 이루어져야 합니다. 이 체인은 다음 syscall 프리미티브를 사용합니다: socket(AF_ALG)/socket(AF_RXRPC), splice, 그리고 unshare(CLONE_NEWUSER|CLONE_NEWNET). ESP 경로는 또한 AF_INET UDP 및 netlink 소켓을 생성합니다. 이 계층이 이 저장소의 탐지 엔지니어링의 초점입니다.
두 변종 모두 동일한 싱크를 사용합니다: 공격자가 splice(2)로 배치한 페이지-캐시 페이지 위에 바이트를 STORE하는 제자리 암호화.
UDP_ENCAP_ESPINUDP로 구성합니다.vmsplice로 파이프에 등록한 다음, splice로 대상 파일 오프셋의 /usr/bin/su에서 16바이트를 등록합니다.splice가 파이프를 송신 소켓으로 밀어 넣습니다. splice_to_socket()은 MSG_SPLICE_PAGES를 설정합니다. 이는 /usr/bin/su의 페이지-캐시 페이지를 skb->frags[0]에 직접 배치합니다.xfrm4_udp_encap_rcv, 이후 xfrm_input, 이후 esp_input(). 취약한 skip_cow 분기(!skb_cloned() && !skb_has_frag_list())는 skb_cow_data()를 우회합니다. 페이지-캐시 페이지를 소스와 대상으로 모두 사용하여 제자리 AEAD 복호화를 수행합니다.crypto_authenc_esn_decrypt()는 ESN의 상위 32비트 STORE를 방출합니다. 해당 값은 replay_esn->seq_hi입니다. 공격자는 SA 등록 시 XFRMA_REPLAY_ESN_VAL netlink 속성으로 이 값을 선택합니다.공격자는 위치(splice 오프셋)와 값(4바이트)을 모두 제어합니다. 인증 검증은 스토어 이후에 실행되므로 암호화 계층은 쓰기를 플래그하지 않습니다. 이 변종은 CAP_NET_ADMIN이 필요하며 unshare(CLONE_NEWUSER|CLONE_NEWNET)를 사용합니다.
rxkad_verify_packet_1()은 splice로 고정된 skb frag에서 직접 단일 블록 pcbc(fcrypt) 복호화를 수행합니다. 먼저 데이터를 복사하지 않습니다. 공격자는 decrypt(ciphertext)가 desired_plaintext와 같도록 세션 키(add_key("rxrpc", …))를 선택합니다. 이는 8바이트 STORE를 생성합니다. 이 변종은 /etc/passwd를 대상으로 합니다. 사용자 네임스페이스가 필요하지 않습니다. rxrpc.ko 모듈이 필요합니다(Ubuntu에서 기본적으로 로드됨).
공개 PoC는 /usr/bin/su를 대상으로 합니다. 각각 4바이트인 48개의 ESP 스토어(파일 오프셋 0에서 192바이트)를 씁니다. 첫 번째 페이지-캐시 바이트를 정적 루트 셸 ELF로 교체합니다. ELF 엔트리 포인트는 setgid(0); setuid(0); setgroups(0,NULL); execve("/bin/sh", …)를 실행합니다. 단일 execve("/usr/bin/su")는 루트 셸을 생성합니다.
ESP 패치(메인라인 f4c50a4034e6)는 splice()를 통해 도착하는 페이지 frag를 SKBFL_SHARED_FRAG 플래그로 표시합니다. esp_input()의 skip_cow 분기는 이제 이 플래그도 확인합니다. 공유 frag skb는 제자리 AEAD 복호화 전에 skb_cow_data()를 거칩니다.
RxRPC 패치(메인라인 aa54b1d27fe0)는 기존 skb_cloned() 확인 옆에 skb->data_len 확인을 추가합니다. 커널은 제자리 pcbc(fcrypt) 복호화 전에 페이지 데이터가 있는 비선형 skb를 복사합니다.
| 구성 요소 | 세부 사항 |
|---|---|
| 하이퍼바이저 | VirtualBox |
| 대상 VM | Kali Linux 2026.1 (취약한 상태로 복원된 스냅샷) |
| 커널 | 6.18.9+kali‑amd64 (2026년 5월 수정보다 이전 버전) |
| 익스플로잇 PoC | V4bel/dirtyfrag (단일 C 파일) |
| 탐지 | auditd (detection/dirtyfrag.rules의 규칙) |
VirtualBox 연구소 설정 스크린샷:

.
├── README.md # 이 연구소 로그
├── detection/
│ ├── dirtyfrag.rules # auditd syscall 수준 탐지 규칙
│ ├── ausearch_dirtyfrag_observed.txt # 실제 익스플로잇 탐지 출력
│ ├── sigma/
│ │ └── dirty_frag_exploit.yml # SIEM 탐지용 Sigma 규칙
│ └── yara/
│ └── dirty_frag_exploit.yar # 디스크/메모리의 PoC 코드용 YARA 규칙
├── mitigation/
│ └── dirtyfrag_mitigation.sh # 모듈 블랙리스트 + 페이지 캐시 플러시
├── poc/
│ └── check_vulnerable.py # 비파괴적 사전 점검 도구
├── reports/
│ └── incident-dirtyfrag.md # 침해 대응 플레이북
└── screenshots/ # 연구소 VM의 실제 캡처
poc/check_vulnerable.py 실행 및 커널/모듈/userns 확인testuser 생성/usr/bin/su 해시와 복원된 해시 캡처drop_caches 또는 재부팅)detection/dirtyfrag.rules 배포 및 auditd 알림 검증reports/incident-dirtyfrag.md)cat /etc/os-release | head -3
uname -r
커널 버전 확인 스크린샷:

커널은 2026년 5월 수정(f4c50a4034e6 / aa54b1d27fe0)보다 이전 버전이어야 합니다. 해당 날짜 이후 apt upgrade를 실행했다면 익스플로잇이 실패합니다. 문제 해결을 참조하세요.
안전한 검사 도구는 VM이 잠재적 대상인지 보고합니다. 실행 중인 커널, esp4/esp6/rxrpc 모듈의 존재, 권한 없는 사용자 네임스페이스 사용 가능 여부를 확인합니다. ESP 변종에는 이러한 네임스페이스가 필요합니다.
python3 poc/check_vulnerable.py
예상 결과: [*] potentially vulnerable -- proceed in a disposable VM only
권한 없는 testuser는 특별한 권한이 없는 공격자를 시뮬레이션합니다.
sudo useradd -m testuser
sudo passwd testuser
su - testuser
id
스크린샷: id가 UID 1001을 표시합니다. 이는 비루트 액세스를 확인합니다.

권한 없는 계정에서:
git clone https://github.com/V4bel/dirtyfrag.git
cd dirtyfrag
gcc -O0 -Wall -o exp exp.c -lutil
./exp
성공 시 익스플로잇은 /usr/bin/su의 페이지 캐시를 패치합니다. 각각 4바이트인 48개의 ESP 스토어(파일 오프셋 0에서 192바이트 루트 셸 ELF)를 씁니다. 그런 다음 forkpty로 대화형 루트 셸을 드롭합니다.
모듈 가용성, 소스 검토 및 깨끗한 컴파일 스크린샷:

id
whoami
스크린샷: ./exp 실행 후 id가 uid=0(root)를 표시합니다.

sha256sum은 페이지 캐시를 통해 읽습니다. 익스플로잇의 쓰기가 활성화된 동안 해시는 원본과 다릅니다. 플러시 후 해시는 원본으로 돌아갑니다. 이 전후 쌍은 디스크의 바이너리가 절대 수정되지 않았음을 증명합니다.