Perché conta
Nel modello classico c’erano solo due stati: root (può tutto) o non-root (quasi niente). Questo creava un problema: un programma che aveva bisogno di un solo potere di root — per esempio aprire la porta 80, riservata a root — doveva girare interamente da root, con tutti i suoi poteri. Le capabilities spezzano l’onnipotenza di root in ~40 permessi distinti, così si può concedere esattamente quello che serve. È il privilegio minimo applicato ai poteri del kernel.
Alcune capabilities chiave
|
|
CAP_SYS_ADMIN è tristemente nota come “il nuovo root”: concede talmente tanto che darla equivale quasi
a dare root. Diffidane.
Leggere e assegnare capabilities sui file
Si possono attaccare a un eseguibile (file capabilities): il programma le ottiene all’esecuzione, senza essere SUID-root. È l’alternativa moderna e più sicura al SUID.
|
|
Il +ep significa effective + permitted: la capability è attiva all’avvio. Perché questo è meglio
del SUID? Perché myapp ottiene solo il potere di aprire porte basse, non l’intero root: se viene
compromesso, l’attaccante non eredita l’onnipotenza.
Azzerare le capabilities nei servizi
Nel sandboxing systemd abbiamo visto
CapabilityBoundingSet=. Qui si chiude il cerchio: si parte da zero e si concede solo lo stretto
necessario.
|
|
Così un web server può legarsi alla 443 pur avendo azzerato ogni altro potere: compromesso, non può caricare moduli kernel, non può ignorare i permessi dei file, non può amministrare la rete.
Verificare le capabilities di un processo
|
|
Conclusione
Le capabilities trasformano il root tutto-o-niente in un insieme di permessi concedibili uno a uno:
un binario ottiene solo CAP_NET_BIND_SERVICE invece di tutto root, un servizio azzera il bounding set
e riceve solo ciò che gli serve. È privilegio minimo a livello di kernel. Ma capabilities e permessi
restano discrezionali; per una politica che nemmeno root o il proprietario possano aggirare serve il
controllo d’accesso obbligatorio: SELinux, prossimo capitolo.