I sistemi Unix, offrono generalmente una funzione che permette di fare funzionare un processo in un file system ridotto, in cui una certa directory diventa temporaneamente la sua nuova directory radice. Si tratta della funzione chroot(), che nel caso di sistemi GNU/Linux, può essere utilizzata solo da un processo con i privilegi dell’utente root.
Le distribuzioni GNU/Linux mettono normalmente a disposizione il programma chroot (1) che permette di utilizzare in pratica questa funzione. In alternativa, ne esiste un’altra versione perfettamente funzionante con GNU/Linux (anche se non si trova nelle distribuzioni), che offre il vantaggio di fondere le funzionalità di chroot e di su; si tratta di chrootuid di Wietse Venema.
187.1 Principio di funzionamento
I programmi di servizio che si occupano di ridefinire la directory radice temporaneamente, per circoscrivere l’ambiente di un processo determinato (e dei suoi discendenti), richiedono l’indicazione della directory che diventerà la nuova directory radice e del programma da avviare al suo interno.
Il processo da avviare in questo ambiente deve trovare lì tutto quello che gli può servire, per esempio le librerie, o altri programmi se il suo scopo è quello di avviare altri sottoprocessi.
È la stessa situazione che si verifica quando si predispone la directory ~ftp/ per l’accesso al servizio FTP anonimo. A titolo di esercizio, può essere preparata una directory del genere riproducendo /bin/, /sbin/, /lib/ e /etc/.
mkdir /tmp/nuova_root
cp -dpR /bin /sbin /lib /etc /tmp/nuova_root
Con quanto preparato in questo modo, si può avviare una shell circoscritta all’ambito della directory /tmp/nuova_root/, che viene fatta diventare appunto la nuova directory radice.
chroot /tmp/nuova_root /bin/bash
Con questo comando, si fa in modo che venga utilizzata la funzione chroot() perché /tmp/nuova_root/ diventi la directory radice per il processo avviato con /bin/bash. È importante comprendere che /bin/bash va inteso qui come parte del sotto-file system e si tratta in generale si /tmp/nuova_root/bin/bash.
Per concludere l’esempio, una volta verificato che si sta lavorando effettivamente in un ambiente ristretto, basta fare terminare il processo per cui è stata cambiata la directory radice, cioè bash.
exit
187.2 Possibilità di questo meccanismo
La definizione di un sotto-file system, permette di isolare il funzionamento di un programma che potrebbe costituire un pericolo di qualche tipo. Per esempio un servizio di rete che si teme possa consentire un qualche accesso non autorizzato.
Si potrebbe immaginare la possibilità di creare delle utenze in cui gli utenti non possano girovagare nel file system, limitandoli all’ambito di un sotto-file system appunto. Tuttavia, dal momento che un sistema GNU/Linux non permette l’utilizzo della funzione chroot() agli utenti comuni, di fatto non è possibile, almeno con i mezzi normali.
187.2.1 Utilizzo di chroot
chroot (2) permette all’utente root di eseguire un comando utilizzando una directory particolare come una nuova directory radice. Il comando, deve essere indicato tenendo conto della situazione che ci si trova di fronte dopo che il cambiamento della directory radice è avvenuto.
chroot directory [comando]
Se non viene indicato alcun comando, viene eseguito /bin/sh, nel sotto-file system a cui ci si riferisce.
Al termine del funzionamento del processo avviato con il comando, si ritorna allo stato precedente, con il file system nelle condizioni in cui si trovava prima.
187.2.2 Utilizzo di chrootuid
chrootuid (3) è un programma simile a chroot, in cui però è possibile indicare l’utente proprietario del processo che viene avviato nella nuova directory radice.
chrootuid directory utente comando
chrootuid non fa parte delle distribuzioni GNU/Linux standard, ma può essere ottenuto facilmente dalla sua origine, presso l’università di Eindhoven in Olanda, ftp://ftp.porcupine.org/pub/security/chrootuid1.3.tar.gz.
187.3 Un esempio pratico: TELNET
In questa sezione si vuole mostrare in che modo potrebbero essere create delle utenze per l’accesso remoto attraverso TELNET, in modo da escludere che gli utenti possano accedere a parti vitali del sistema. L’esempio viene indicato solo in linea di massima, trascurando dettagli che devono poi essere definiti da chi volesse utilizzare tale sistema realmente e in modo serio.
Per semplificare le cose, si può creare una copia del sistema in funzione, a partire da una sottodirectory (ammesso che ci sia abbastanza spazio disponibile nel disco fisso). Si suppone di farlo nella directory /sicura/.
mkdir /sicura
cp -dpR /bin /dev /etc /home /lib /opt /root /sbin /usr /var /sicura
mkdir /sicura/tmp
chmod 1777 /sicura/tmp
mkdir /sicura/proc
chmod 0555 /sicura/proc
Quindi si «entra» in questo sistema e si fa un po’ di pulizia, eliminando in particolare tutto quello che nella directory etc/ non serve. Infatti, si deve considerare che in questo piccolo ambiente non esiste una procedura di inizializzazione del sistema, non esiste l’avvio di programmi demone e non si configura la rete. L’unica attenzione deve essere data alla configurazione delle shell che si vogliono poter utilizzare.
chroot /sicura
…
exit
Il sistema circoscritto appena creato, può avere delle difficoltà a funzionare in un sistema GNU/Linux, a causa della mancanza del contenuto della directory proc/ che dovrebbe essere montato anche lì. Questo inserimento può essere definito convenientemente una volta per tutte nel file /etc/fstab del file system normale, avendo così due punti di innesto diversi e simultanei.
/etc/fstab
…
none /proc proc defaults 0 0
none /sicura/proc proc defaults 0 0
#…
Si potrebbe valutare la possibilità di non lasciare l’accessibilità alle informazioni di questa directory. Si può provare a vedere se le attività che si vogliono concedere agli utenti sono compromesse dalla sua mancanza. Se il disagio è tollerabile, è meglio evitare di montare la directory /proc/ quando tutto è pronto.
Una volta sistemato questo particolare, tutto funziona meglio nel sistema che si articola dalla directory /sicura/. Per fare in modo che il servizio TELNET utilizzi questo spazio riservato, si deve modificare il file di configurazione del supervisore dei servizi di rete del file system normale; per esempio, nel caso di Inetd, il file /etc/inetd.conf va modificato in un modo simile a quello seguente:
telnet stream tcp nowait root /usr/sbin/tcpd /sicura/telnetd
Come si vede, per l’avvio del servizio è stato indicato l’eseguibile /sicura/telnetd, che in pratica è uno script di shell che contiene la chiamata del comando chroot, prima dell’avvio del vero demone in.telnetd.
! /bin/sh
chroot /sicura /usr/sbin/in.telnetd
In questo caso, quanto indicato come /usr/sbin/in.telnetd, è in realtà /sicura/usr/sbin/in.telnetd.
Una volta definito questo, dopo aver montato anche la directory /sicura/proc/ e dopo aver riavviato il supervisore dei servizi di rete, si può accedere con un cliente TELNET nel proprio sistema locare come utente root, per sistemare le cose (per farlo, temporaneamente, occorre che il file /sicura/etc/securetty preveda anche i dispositivi /dev/ttyp*, oppure quelli che sono utilizzati effettivamente per l’accesso attraverso TELNET).
Una volta sistemate le cose come si desidera, si dovrà avere cura di impedire l’accesso remoto da parte dell’utente root, tenendo conto che al limite questo utente potrebbe anche essere cancellato all’interno di /sicura/etc/passwd
telnet localhost
Una volta entrati nel mini sistema, dopo essersi accertati che funziona (basta creare un file e su un’altra console virtuale vedere che si trova collocato a partire dalla directory /sicura/), si comincia a disinstallare tutto quello che non serve e che non si vuole lasciare usare agli utenti. Probabilmente, tutto quello che riguarda la configurazione della rete dovrebbe essere eliminato, mentre qualche cliente particolare potrebbe essere lasciato a disposizione degli utenti.
Anche la directory dev/ dovrebbe essere controllata, lasciando al suo interno solo i dispositivi indispensabili. Di certo non servono i dispositivi che permettono l’accesso a unità di memorizzazione: gli utenti remoti non devono avere la possibilità di montare o smontare dischi.
Gli stessi file etc/passwd e etc/group (ed eventualmente etc/shadow) possono essere modificati per eliminare tutti gli utenti di sistema, compreso root che potrebbe essere aggiunto nel momento in cui si volesse fare qualche intervento dall’interno). In pratica, si tratterebbe di lasciare solo gli utenti del servizio TELNET.