
Linux 커널 FUSE readdir 캐시 범위 초과 쓰기 (CVE-2026-31694): 악성 FUSE 서버가 페이지 캐시 페이지를 24바이트만큼 오버플로우시킵니다. PoC 및 /etc/passwd 페이지 캐시 손상을 통한 권한 없는 로컬 루트 익스플로잇을 포함합니다. 가상 머신 내에서만 실행하십시오.
fs/fuse/readdir.c:fuse_add_dirent_to_cache()에 경계 검사 누락이 있습니다. FUSE 서버가 namelen = 4095인 dirent를 반환하면, 이는 4120바이트 레코드로 직렬화됩니다. 커널이 이를 하나의 4096바이트 페이지 캐시 페이지에 복사하고, 서버가 제어하는 24바이트가 다음 물리 페이지로 오버플로됩니다.
이 저장소에는 쓰기 프리미티브에 대한 마커 PoC와, 오버플로를 페이지 캐시에 있는 /etc/passwd의 복사본으로 조작하여 root를 비밀번호 없는 계정으로 만드는 로컬 권한 상승(LPE)이 포함되어 있습니다.
FUSE_NAME_MAX가 PATH_MAX - 1로 증가하여 readdir 경로에 도달 가능)51a8de6c50bf9 "fuse: reject oversized dirents in page cache" (5개의 안정 백포트 중 하나)이 오버플로는 FUSE 캐시 페이지 바로 뒤에 있는 물리 페이지에 대한 커널 쓰기입니다. 이 조작은 해당 쓰기를 선택한 페이지로 향하게 하지만 확률적입니다. 실패 시 24바이트가 관련 없는 페이지에 충돌할 수 있습니다:
일회용 VM 내부에서만 실행하십시오. 여기에 있는 스크립트는 항상 QEMU/KVM 내부에서 익스플로잇을 실행하며, 호스트에서는 실행하지 않습니다.
exploit.c PoC 및 LPE (단일 파일, 정적 빌드)
Makefile ./exploit 빌드 (정적)
vm/config.sh 모든 경로 및 설정 (KERNEL_TREE 편집)
vm/make_rootfs.sh Ubuntu 24.04 게스트 이미지 빌드 (root로 실행)
vm/build_vuln_kernel.sh 커널 트리에서 취약한 bzImage 빌드
vm/run_vm.sh 게스트를 헤드리스로 부팅
vm/provision_guest.sh 게스트 내 설정 (ssh를 통해 실행)
vm/run_in_vm.sh 하나의 명령: 부팅, 프로비저닝, 실행, 확인
호스트: KVM이 있는 Linux (/dev/kvm이 존재하고, 사용자가 kvm 그룹에 속해야 함), 그리고:
qemu-system-x86_64, sshpass, gcc, makemake_rootfs.sh의 경우: debootstrap (및 root 권한)취약한 커널을 빌드하려면 Linux 커널 소스 트리도 필요합니다.
vm/config.sh를 편집합니다. 반드시 설정해야 하는 값은 KERNEL_TREE 뿐입니다: Linux 소스 체크아웃의 경로입니다. 수정 51a8de6c50bf9 이전의 버전(6.15..7.0 체크아웃에는 버그가 있음)을 사용하십시오. 트리에 이미 수정이 적용된 경우, build_vuln_kernel.sh는 빌드 시 해당 보호를 제거하고 이후 파일을 복원합니다. 다른 모든 항목(메모리, CPU, SSH 포트, 이미지 경로)은 기본값이 있으며 그대로 두어도 됩니다. 환경 변수를 통해 값을 설정할 수도 있습니다(예: KERNEL_TREE=/path/to/linux vm/run_in_vm.sh).
게스트 이미지(Ubuntu 24.04, debootstrap을 위해 root 필요)를 빌드합니다:
sudo vm/make_rootfs.sh
이렇게 하면 test:test sudo 사용자, 직렬 콘솔, SSH 비밀번호 인증 및 fuse3가 생성됩니다.
취약한 커널을 빌드합니다:
vm/build_vuln_kernel.sh
종단 간 (부팅, 프로비저닝, 마커 PoC, LPE, uid 0 확인):
vm/run_in_vm.sh
수동:
vm/run_vm.sh & # 헤드리스 부팅; 콘솔은 vm/serial.log로
make # 정적 익스플로잇 빌드
# ./exploit를 게스트에 복사한 후 test 사용자로:
./exploit --poc -n 20 # 마커 테스트
./exploit # 웜업 후 LPE
VM 중지:
pkill -f bzImage-fuse-vuln
--poc 마커 모드만, /etc/passwd 변경 없음
-n N 라운드 수
(인수 없음) 5회 웜업 라운드, 그 후 최대 200회 LPE 시도; 성공 시 /etc/passwd에 비밀번호 없는 root 라인을 쓰고 캐시를 비움
마커 모드는 라운드별 히트와 총합을 출력합니다(예: 20/20 (100.0%)).
LPE 모드는 Warmup: 5/5를 출력한 후, LPE n/200 ... HIT! 라인을 출력하고, /etc/passwd의 첫 번째 줄을 root:x:0:0:root:/root:/bin/bash에서 root::0:0:root:/root:/bin/sh로 변경합니다. 그 다음 빈 비밀번호로 su -s /bin/sh root를 실행하면 uid 0이 반환됩니다.
readdir 캐시 경로는 각 dirent를 페이지 캐시 페이지에 복사합니다. 크기 검사는 dirent가 현재 페이지의 남은 공간에 맞는지만 묻고, dirent가 페이지에 전혀 맞는지는 묻지 않습니다. namelen = 4095인 경우 레코드는 4120바이트이므로, 복사는 새 페이지의 끝에서 24바이트를 초과하여 실행됩니다.
익스플로잇은 CPU별 페이지(PCP) 프리리스트를 비워 할당자가 버디 분할에서 물리적으로 인접한 페이지를 제공하도록 한 후, readdir 캐시 페이지와 대상 페이지를 이웃하도록 배치합니다. LPE의 경우 대상은 /etc/passwd의 페이지 캐시 복사본입니다: 24바이트 오버플로가 root의 라인을 덮어써서 비밀번호 필드를 비우고, PAM nullok(Ubuntu 기본값)을 통해 빈 비밀번호로 su root가 성공합니다.
전체 글: https://cyberstan.co.uk/fuse-readdir-oob/
Qi Tang과 Zijun Hu가 업스트림에 보고했으며, 수정은 Samuel Page가 작성했습니다. 저는 독립적으로 이를 발견하고 보고했습니다. 업스트림 크레딧과 CVE-2026-31694는 그들의 것입니다. 이 버그는 메인라인 및 안정 트리에서 수정되었습니다.
MIT, LICENSE 참조. 교육 및 승인된 테스트용으로만 사용하십시오.