L'evoluzione di sudo: da su di Unix ai privilegi moderni
Scopri l'evoluzione di sudo dal comando su di Unix alle alternative moderne come doas, polkit e run0. Rischi di sicurezza e buone pratiche.

Ecco un fatto che sorprende la maggior parte delle persone: quando digiti la password in sudo, non vedi alcun feedback. Nessun asterisco, nessun puntino, niente. Il cursore resta semplicemente fermo lì. Questa scelta progettuale risale agli anni '80 e confonde gli utenti da oltre quarant'anni. Molti pensano che il terminale si sia bloccato, digitano la password più volte o credono che qualcosa sia rotto. Ubuntu ha finalmente deciso di mostrare gli asterischi per impostazione predefinita, mettendo fine a una tradizione di 46 anni di inserimento silenzioso della password.
Questo piccolo cambiamento rivela qualcosa di più grande: il modo in cui Linux gestisce l'escalation dei privilegi è un insieme di decisioni prese nel corso dei decenni, alcune brillanti, altre decisamente discutibili, tutte portate avanti dal peso della retrocompatibilità. Capire come siamo arrivati qui ti aiuta a prendere decisioni di sicurezza migliori oggi.
Prima di sudo: il mondo di su
Lo strumento originale di escalation dei privilegi in Unix era su — « substitute user ». Faceva esattamente una cosa: cambiava l'intera sessione della shell su un altro utente, tipicamente root. Digitavi su, inserivi la password di root, svolgevi il lavoro di amministrazione e poi uscivi tornando al tuo account normale.
$ su
Password: [type root's password]
# whoami
root
# apt install nginx
# exit
$ whoami
normaluser
I problemi di su sono diventati evidenti man mano che i sistemi Unix crescevano oltre una manciata di operatori fidati. Tutti quelli che avevano bisogno di accesso amministrativo dovevano conoscere la password di root. Quando qualcuno lasciava il team, bisognava cambiare la password di root e comunicare quella nuova a tutti gli altri. Non c'era alcuna traccia di audit: una volta diventato root, ogni azione veniva registrata come « root », senza sapere chi avesse eseguito cosa. E su ti dava una shell root completa, il che significava che un solo errore di battitura poteva distruggere il sistema.
La classica storia dell'orrore: un amministratore voleva digitare rm -rf /tmp/old_files ma ha premuto invio dopo aver scritto rm -rf /. Con una shell root completa, nulla impedisce a quel comando di essere eseguito. su non faceva alcuna distinzione tra « questa persona deve riavviare nginx » e « questa persona deve avere accesso illimitato all'intero sistema ».
Come sudo ha risolto il problema della password di root
sudo (« superuser do ») è stato creato nel 1980 alla SUNY Buffalo da Bob Coggeshall e Cliff Spencer. L'intuizione di fondo era semplice ma trasformativa: invece di condividere la password di root, permettere ai singoli utenti di eseguire comandi specifici come root usando la propria password. L'amministratore di sistema controlla chi può eseguire cosa tramite un file di configurazione.
Questo ha risolto diversi problemi in una volta sola:
- Nessuna password di root condivisa. Ogni utente si autentica con le proprie credenziali. Quando qualcuno lascia il team, gli revochi l'accesso a sudo. Non serve alcuna rotazione della password.
- Permessi granulari. Puoi permettere a uno sviluppatore di riavviare un servizio specifico senza dargli pieno accesso root.
- Traccia di audit. Ogni comando sudo viene registrato con il nome utente di chi l'ha eseguito, cosa ha eseguito e quando.
- Escalation temporanea. Invece di una shell root senza limiti, sudo esegue un singolo comando con privilegi elevati e poi torna al normale livello di utente.
# Run a single command as root
$ sudo apt install nginx
[sudo] password for priya:
# That's YOUR password, not root's
# The audit trail in /var/log/auth.log:
# Mar 20 14:23:01 web-03 sudo: priya : TTY=pts/0 ;
# PWD=/home/priya ; USER=root ; COMMAND=/usr/bin/apt install nginx
Il file sudoers: potente e pericoloso
La configurazione di sudo si trova in /etc/sudoers, e la sua sintassi è davvero una delle cose più confuse nell'amministrazione Linux. Un singolo errore di sintassi può escluderti completamente da sudo, ed è per questo che esiste il comando visudo: convalida il file prima di salvarlo.
# /etc/sudoers syntax:
# WHO WHERE = (AS_WHOM) WHAT
# Let priya run anything as root on any host
priya ALL=(ALL:ALL) ALL
# Let the 'webdev' group restart nginx only
%webdev ALL=(root) /usr/bin/systemctl restart nginx,\
/usr/bin/systemctl reload nginx
# Let deploy user run deploys without a password
deploy ALL=(root) NOPASSWD: /opt/deploy/run.sh
# DANGEROUS: This looks restrictive but isn't
bob ALL=(root) /usr/bin/vim
# Bob can now run: sudo vim, then :!bash to get a root shell
Quell'ultimo esempio — dare a qualcuno l'accesso a sudo per vim — è una trappola di sicurezza in cui le persone cadono continuamente. Vim (e molti altri programmi) può avviare comandi di shell. Se un utente può eseguire sudo vim, di fatto ha accesso root illimitato. Lo stesso vale per less, man, awk, find, python e decine di altri comandi. Il progetto GTFOBins mantiene un elenco completo dei binari che possono essere usati per uscire dalle shell ristrette.
Le stranezze e i rischi di sicurezza di sudo
sudo ha accumulato alcuni comportamenti davvero strani nei suoi oltre 40 anni di storia. Capirli è importante per la sicurezza:
- Cache delle credenziali. Dopo aver inserito la password, sudo la memorizza nella cache per 15 minuti per impostazione predefinita. Durante questa finestra, qualsiasi comando sudo viene eseguito senza autenticazione. Se ti allontani da un terminale sbloccato, chiunque può eseguire comandi sudo per un massimo di 15 minuti. Esegui
sudo -kper svuotare subito la cache. - L'impostazione tty_tickets. Per impostazione predefinita, la cache delle credenziali di sudo è per terminale. Ma su alcuni sistemi, autenticarsi in una sessione di terminale sblocca sudo in tutte le altre. Controlla le impostazioni
Defaults. - Variabili d'ambiente. sudo ripulisce la maggior parte delle variabili d'ambiente, ma non tutte.
LD_PRELOADeLD_LIBRARY_PATHvengono rimosse, ma seenv_keepè configurato in modo errato, un attaccante può iniettare percorsi di librerie malevole. Questo è alla base di diversi exploit reali di escalation dei privilegi. - La trappola di NOPASSWD.
NOPASSWDè comodo per l'automazione, ma pericoloso se applicato in modo troppo ampio. Un'applicazione compromessa che gira come utente con accesso sudoNOPASSWDha di fatto i privilegi di root — senza una password da craccare.
# Security hardening for sudoers:
# Require password every time (disable caching)
Defaults timestamp_timeout=0
# Or reduce cache to 1 minute
Defaults timestamp_timeout=1
# Ensure credential cache is per-terminal
Defaults tty_tickets
# Log all sudo I/O (records full terminal sessions)
Defaults log_input, log_output
Defaults iolog_dir=/var/log/sudo-io
# Require root password instead of user password
# (prevents compromised user accounts from sudo-ing)
Defaults rootpw
# Show asterisks when typing password
Defaults pwfeedback
Alternative moderne: doas, polkit e run0
La complessità di sudo ha generato diverse alternative, ciascuna con una filosofia diversa.
doas: sudo senza la complessità
doas di OpenBSD (« dedicated OpenBSD application subexecutor ») è stato creato da Ted Unangst nel 2015 proprio perché sudo era diventato troppo complesso da verificare. L'intera configurazione è tipicamente di 2-3 righe:
# /etc/doas.conf — the entire configuration
permit persist priya
permit nopass deploy as root cmd /opt/deploy/run.sh
# That's it. Compare this to a typical sudoers file.
# 'persist' is like sudo's credential caching
# 'nopass' is like NOPASSWD
Il codice sorgente di doas è di circa 2.500 righe di C. Quello di sudo supera le 150.000. Per i sistemi che non richiedono le funzionalità avanzate di sudo (come il controllo degli argomenti per singolo comando o l'integrazione con LDAP), doas è molto più semplice da configurare, verificare e proteggere. Lo uso sui miei server personali da anni e non ho mai sentito la mancanza di sudo.
polkit: privilegi desktop a grana fine
PolicyKit (polkit) adotta un approccio completamente diverso. Invece di incapsulare i singoli comandi, definisce azioni che le applicazioni possono richiedere. Quando un'app desktop ha bisogno di modificare le impostazioni di rete, chiede a polkit il permesso, e polkit decide in base alle sue regole se concederlo, negarlo o chiedere conferma all'utente.
È così che il desktop Linux ti permette di montare una chiavetta USB senza password, ma richiede l'autenticazione per installare software. La granularità è a livello di azione, non di comando, e questo corrisponde meglio a come gli utenti desktop pensano ai permessi.
run0: la radicale riprogettazione di systemd
run0 di systemd è l'ultimo arrivato e funziona in modo sostanzialmente diverso da sudo. Invece di eseguire un comando come root dalla sessione esistente (il che richiede bit setuid e crea grattacapi di sicurezza), run0 chiede al service manager di avviare un nuovo servizio che gira come root. La sessione utente non ottiene mai privilegi elevati: il processo privilegiato è completamente separato.
Questo aggira intere categorie di vulnerabilità di sudo: non c'è un binario setuid, nessuna cache delle credenziali, nessuna superficie di iniezione tramite variabili d'ambiente. Il compromesso è che richiede systemd, il che lo rende inadatto ai sistemi BSD e alle installazioni Linux minimali. Ma per i server basati su systemd, è probabilmente l'opzione più sicura disponibile.
Raccomandazioni pratiche
Dopo anni di gestione di server Linux e di indagini su incidenti di escalation dei privilegi, ecco cosa consiglio davvero:
- Disabilita del tutto il login di root. Usa
sudoodoasper tutto. Non dovrebbe esistere alcuna password di root condivisa. - Nel sudoers usa gruppi, non singoli utenti. Gestisci gli accessi tramite l'appartenenza ai gruppi. Quando qualcuno lascia il team, rimuovilo dal gruppo.
- Non dare mai accesso sudo a interpreti o editor. Niente
sudo vim,sudo python,sudo less. Se devi modificare un file di proprietà di root, usa invecesudoedit. - Riduci al minimo le regole NOPASSWD. Usale solo per processi automatizzati e solo per comandi specifici con percorso completo.
- Abilita il logging di sudo. Come minimo, registra tutti i comandi sudo. Per i sistemi sensibili, attiva il logging completo di I/O.
- Valuta doas per sistemi più semplici. Se non ti servono l'integrazione con LDAP o regole di corrispondenza complesse, doas è più facile da configurare correttamente.
- Riduci al minimo la cache delle credenziali. Imposta
timestamp_timeouta 1-5 minuti, oppure disabilita la cache del tutto sui server di produzione.
Il miglior meccanismo di escalation dei privilegi è quello che concede il minimo accesso necessario, per il minimo tempo necessario, con una traccia di audit completa. Tutto il resto è un compromesso.
sudo non va da nessuna parte. È troppo radicato in script, automazioni, documentazione e abitudini consolidate per sparire. Ma il panorama delle alternative è più sano che mai. Che tu scelga di restare con sudo (configurato in modo sicuro), di passare a doas (per la semplicità) o di adottare run0 (per i sistemi critici dal punto di vista della sicurezza), la cosa importante è capire cosa fa davvero il tuo strumento di escalation dei privilegi — perché il divario tra ciò che le persone pensano che sudo faccia e ciò che fa davvero è dove si annidano la maggior parte degli incidenti di sicurezza.


