La storia dei tre bit

Diventate il geek alfa del vostro gruppo imparando a conoscere setuid, setgid e il misterioso bit appiccicoso

Tutti conoscono i nove bit di modo che definiscono

i permessi di accesso a un file (il rwxrwxrwx che mostra il comando ls -l), ma, oltre a questi, ci sono altri tre bit di modo che sono molto meno conosciuti. Questo mese ho deciso

di portarli al centro della scena. Da sinistra a destra sono:

  • il bit set user ID, per gli amici setuid
  • il bit set group ID, setgid in breve
  • Il bit sticky (appiccicoso in inglese).

Questi tre bit possono essere alzati e abbassati proprio come ogni altro bit di modo. Per esempio

$ chmod u+s foo
$ chmod g+s foo
$ chmod +t foo

alzano rispettivamente il setuid, setgid e sticky bit. Se invece preferite esprimere i bit di modo con numeri ottali, dovete sapere che il bit setuid ha valore ottale 4000, il setgid 2000 e il bit sticky 1000. Quindi, ad esempio, il comando

$ chmod 4755 foo

renderà foo eseguibile da tutto il mondo e alzerà il bit setuid.

Comprendere l’output di ls -I

Il modo con cui ls -I visualizza questi bit è bizzarro. A prima vista la soluzione owia sarebbe stata quella di aggiungere altri tre caratteri all’inizio della riga. Invece vengono modificati i tre caratteri che indicano i permessi di esecuzione, come indicato nel diagramma qui sotto. Quindi il bit setuid viene evidenziato come una s nella posizione del bit di esecuzione del proprietario, il setgid nella posizione del bit di esecuzione del gruppo e il bit sticky appare come una t nella posizione del bit di esecuzione del mondo.

La seguente sequenza di comandi può essere utile:

$ ls -l foo
-rwxr-xr-x 1 chris chris 833592 2019-02-16
11:07 foo
$ chmod u+s foo # Alza il bit setuid
$ ls -l foo
-rwsr-xr-x 1 chris chris 833592 2019-02-16
11:07 foo
$ chmod g+s foo # Alza il setgid bit
$ ls -l foo
-rwsr-sr-x 1 chris chris 833592 2019-02-16 11:07 foo
$ chmod +t foo # Alza il bit sticky
$ ls -l foo
-rwsr-sr-t 1 chris chris 833592 2009-02-16 11:07 foo
$ chmod 4755 foo # bit setuid, usando l’ottale
$ ls -l foo
-rwsr-xr-x 1 chris chris 833592 2009-02-16
11:07 foo

 

C’è ancora qualcosa che non molti conoscono. Dato che le s e la t coprono i permessi di esecuzione nell’output del comando ls -l, come facciamo a sapere se sono disponibili? La risposta è: nel caso che il sottostante bit di esecuzione non sia alzato verrà stampata una S o una T maiuscola. Per esempio:

$ chmod 4644 foo
$ ls -l foo
-rwSr--r-- 1 chris chris 833592 2019-02-16
10:51 foo

È una situazione che non dovrebbe mai presentarsi: se un programma deve essere eseguito con setuid ha bisogno innanzitutto di poter essere eseguito. Ecco un caso estremo:

$ chmod 7000 foo
$ ls -l foo
---S--S--T 1 chris chris 833592 2019-02-16
11:07 foo

L’unico uso che mi viene in mente per queste cose è quello di dare una dimostrazione della vostra bravura a un amministratore di sistema particolarmente presuntuoso.

Setuid

Ora che abbiamo imparato come si fa a impostare questi bit di modo aggiuntivi e a esaminarne lo stato vediamo a cosa servono in pratica, illustrando anche alcuni utili scenari di applicazione. Il bit setuid è senza dubbio la primadonna del nostro spettacolo. Quando viene applicato a un file eseguibile fa in modo che come ID utente effettivo (effective user ID) del processo venga usato l’ID dell’utente a cui appartiene il file, di solito root. Come molti di voi sapranno, ogni processo è dotato di due identificativi utente: la sua identità reale e quella effettiva. È quest’ultima che viene usata dal kernel per prendere decisioni relative al controllo degli accessi per il processo. Se il bit setuid non è alzato le due identità coincidono e ad entrambe viene assegnata l’identità dell’utente che ha lanciato il programma. Questa elegante funzionalità di Linux è di importanza fondamentale, dato che sta alla base di tutti gli strumenti per l’innalzamento dei privilegi, come ad esempio sudo. È facile trovare esempi di impiego del bit setuid. Supponete di aver scritto un gioco (lo chiameremo Spacewar, anche se temo che il nome sia stato già usato nel 1961 ) e che vogliate conservare in un file i nomi dei 10 giocatori con i punteggi più alti. Owiamente non potete dare il permesso di scrittura sul file al mondo, altrimenti qualcuno potrebbe barare: il programma deve invece essere in grado di scrivere sul file per conto del giocatore quando decide che il punteggio va registrato. La soluzione consiste nel definire un nuovo utente, lo chiameremo spaceman, che non sarà possibile utilizzare per il login, ma che verrà usato unicamente come proprietario del file del punteggio.Create poi il file del punteggio, assicurandovi che appartenga a spaceman e sia scrivibile solo dal proprietario. Potreste ad esempio fare così:

# cd /var/run
# mkdir spacewar
# cd spacewar
# touch migliori-punteggi
# chown spaceman migliori-punteggi
# chmod 644 migliori-punteggi

Questi comandi creano un file che è leggibile da tutti ma scrivibile solo dall’utente spaceman. Il trucco consiste nell’assegnare spacewar come proprietario del file che contiene il gioco e nell’alzare il bit setuid del file:

# cd /usr/local/bin
# chown spaceman spacewar
# chmod 4755 spacewar

A questo punto il file spacewar sarà eseguibile da tutti e verrà eseguito con i permessi effettivi di spaceman, quindi sarà in grado di scrivere nel file del punteggio.

Approfondiamo setuid

Il classico esempio di un programma setuid è passwd, che permette agli utenti normali di cambiare la loro password scrivendo un hash della loro nuova password nel file /etc/shadow. Esaminiamo attentamente proprietà e permessi dei due file:

$ ls -l /usr/bin/passwd /etc/shadow
-rwsr-xr-x 1 root root 42776 2019-02-16 06:50 /usr/bin/
-rw-r----- 1 root shadow 1262 2019-02-16 16:16
/etc/shadow
passwd

Il programma per la modifica delle password è eseguibile dal mondo e gira come setuid root, permettendo cosi di scrivere sul file che contiene le password. I programmi con il bit setuid alzato, specialmente se sono di proprietà di root, devono essere affidabili e resistenti ai tentativi di indurli a compiere azioni non previste dall’autore. L’applicazione del principio del minimo privilegio suggerisce che, se c’è necessità di elevare i privilegi, è meglio farlo verso un utente diverso da root, come nel caso del nostro esempio con il gioco Spacewar. Detto questo, su RHELS ho contato ben 34 programmi setuid, ognuno dei quali di proprietà di root Il bit setuid costituisce un’autentica minaccia alla sicurezza quando è usato in combinazione con un supporto rimovibile. Lo scenario è il seguente: il signor Pessimo Soggetto crea un CD sul PC di casa e ci mette sopra una copia della Bash di proprietà di root e con il bit setuid alzato. Poi porta il CD al lavoro, lo inserisce in un server, aspetta che il montaggio automatico faccia il suo lavoro et voilà, una shell di rootl Cosa gli impedisce di fare danni7 Beh, per default solo root può montare un f1lesystem. Per abilitare gli utenti diversi da root a montare supporti rimovibili occorre specificare l’opzione di montaggio user nella riga di /etc/fstab corrispondente. Questa opzione implica le opzioni noexec, nosuid e nodev, che significano (tra le altre cose) che il bit setuid non verrà preso in considerazione per nessun file presente sul filesystem montato.

Il doppio lavoro di setgid

Il bit setgid, applicato a un file eseguibile, lavora in modo simile a setuid, ma assegna all’ID di effettivo gruppo (e{tective group ID) del processo l’ID del gruppo a cui appartiene il file. È un altro modo di elevare i privilegi. Secondo me è difficile pensare a un qualche scenario che lo sfrutti appieno, anche se è usato, ad esempio, dai componenti postdrop e postqueue del sistema di posta Postfix. Ho sempre l’impressione che setgid sia in qualche modo messo in secondo piano rispetto a setuid, come l’ultimo dei Mohicani. Però setgid ha anche un’altra funzione quando viene applicato a una directory: cambia le regole di appartenenza a un gruppo dei file creati nella directory. Il comportamento normale, naturalmente, è che il gruppo di appartenenza di un file appena creato è il gruppo primario dell’utente che lo ha creato.Con il bit setgid alzato invece il gruppo viene ereditato da quello della directory. Questo permette di realizzare interessanti condivisioni all’interno di un gruppo di utenti.

Il ritorno del bit appiccicoso

Agli inizi di UNIX il bit sticky significava: mantieni l’immagine di questo eseguibile nell’area di swap dopo che l’esecuzione è terminata, perché probabilmente ne avrò bisogno tra poco. Immagino che fosse usato per programmi come la shell,gli editor e il compilatore C. Dischi più veloci e la memoria virtuale paginata hanno reso superfluo il bit sticky e ne hanno interrotto la carriera per molti anni. Di recente però ha fatto una rentrée su Linux con un ruolo molto diverso. Applicato a una directory modifica le regole relative ai permessi di cancellazione dei file. Senza il bit sticky alzato chiunque può cancellare un file da una directory, anche se non è il proprietario del file, purché abbia il permesso di scrivere nella directory. Quando il bit sticky è alzato invece solo il proprietario del file può cancellarlo. Per essere precisi dovremmo chiamarlo bit di limitazione della cancellazione, ma il termine bit sticky gli è rimasto … appiccicato. Classicamente il bit sticky è usato per le directory condivise come /tmp. Su Linux non ha invece nessun significato quando viene applicato a un file.

Bit vari

I file che hanno il bit setuid, setgid o sticky alzato sono relativamente pochi e sparsi qua e là, ma è possibile trovarli facilmente usando l’opzione -perm di find. Date il seguente comando per trovare tutti i file appartenenti a root e con il bit setuid alto:

sudo find / -perm /4000 -user root

Per trovare tutte le directory con il bit setgid impostato invece:

sudo find / -type d -perm /2000

mentre per trovare quelle con il bit sticky alto

sudo find / -type d -perm /1000

Per concludere, ecco il comando che permette di trovare tutti i file che non sono directory e hanno il bit sticky alto (probabilmente per errore):

sudo find / -type f -perm /1000