Vai al contenuto
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after a top-up of $10 or more. Until Nov 30.

How it works

Permessi Linux: utenti, gruppi, chmod e umask

Proprietari e gruppi Linux, bit rwx, chmod, umask e setuid, con un lab che prova l'accesso come secondo utente e trova i permessi rischiosi sui file.

Base13 min di letturaDi NotHoly

I permessi di Linux decidono chi può leggere, modificare ed eseguire ogni file del sistema. La maggior parte dei problemi che incontri in una revisione di sicurezza non sono exploit esotici. Sono un file di configurazione che qualsiasi account locale può scrivere, uno script eseguito da un servizio root ma modificabile da un utente normale, o un binario con il bit setuid che nessuno ricorda di aver aggiunto. Questo articolo spiega il meccanismo partendo dal basso: proprietari, gruppi, i bit rwx, chmod, umask e i bit speciali che contano di più in una revisione. Creerai file, ne cambierai la modalità, proverai l'accesso come secondo utente locale in una VM di laboratorio e cercherai i permessi rischiosi.

L'idea di fondo è il privilegio minimo. Un processo dovrebbe avere solo l'accesso che gli serve, e un file dovrebbe essere scrivibile solo dalle persone e dai programmi che devono modificarlo. Le modalità dei file sono il primo punto in cui Linux applica questa regola, quindi sono la prima cosa da controllare.

Cos'è un permesso su un file

Ogni file e directory ha tre cose che decidono l'accesso:

  1. Un proprietario, un account utente.
  2. Un gruppo, un account di gruppo.
  3. Una modalità, un insieme di bit che dice cosa possono fare il proprietario, il gruppo e tutti gli altri.

Esegui questo comando su un file qualsiasi nella tua home:

bash
ls -l notes.txt

Il primo carattere è il tipo di file (- è un file normale, d una directory, l un collegamento simbolico). I nove caratteri successivi sono la modalità. I nomi di proprietario e gruppo vengono dopo il numero di collegamenti.

Il kernel controlla i permessi ogni volta che un processo apre un file. Una shell, un server web e un job cron passano tutti per lo stesso controllo. Se il controllo fallisce, ottieni Permission denied. Al file system non interessa se il processo è fidato.

Proprietari, gruppi e tutti gli altri

La modalità ha tre terne, una per ogni classe di utente:

  • User (u): l'account proprietario del file.
  • Group (g): i membri del gruppo proprietario del file.
  • Other (o): ogni account che non è né il proprietario né un membro del gruppo.

Linux controlla le classi in ordine. Se il tuo account è il proprietario, si applicano i bit del proprietario e quelli di gruppo e degli altri vengono ignorati, anche quando concederebbero di più. Questo sorprende molti. Un file i cui bit del proprietario sono --- non si apre per il suo proprietario, anche se i bit del gruppo sono rwx e il proprietario appartiene a quel gruppo.

L'appartenenza ai gruppi è un elenco separato. Controlla la tua con:

bash
id
groups

Una modifica all'appartenenza a un gruppo di solito ha effetto al login successivo, non nella shell in cui hai eseguito il comando.

Leggere i bit rwx

Ogni terna contiene tre bit:

Bit Su un file normale Su una directory
r (lettura, valore 4) Leggere il contenuto Elencare i nomi al suo interno
w (scrittura, valore 2) Modificare il contenuto Creare, rinominare o cancellare voci
x (esecuzione, valore 1) Eseguirlo come programma Entrare nella directory e raggiungere le sue voci

Due punti fanno inciampare chi inizia.

Primo, il bit x di una directory è quello che ti permette di attraversarla. Una directory con r ma senza x ti permette di vedere i nomi ma non di aprirli. Una directory con x ma senza r ti permette di aprire un file di cui conosci già il nome esatto, ma non di elencare la directory.

Secondo, il permesso di scrittura su un file non ti permette di cancellarlo. La cancellazione dipende dai permessi di scrittura ed esecuzione sulla directory che contiene la voce. Se un file è tuo ma sta in una directory in cui non puoi scrivere, non puoi comunque rimuoverlo.

Notazione simbolica e ottale

chmod accetta due notazioni per la stessa cosa.

Ottale. Ogni terna diventa una cifra, la somma dei suoi bit: r vale 4, w vale 2, x vale 1. Quindi rw- è 6, r-- è 4, r-x è 5 e rwx è 7. La modalità 644 significa lettura e scrittura per il proprietario (6), lettura per il gruppo (4), lettura per gli altri (4). La modalità 600 significa che solo il proprietario può leggere o scrivere.

Simbolica. Indichi la classe, l'operatore e i bit:

  • Classi: u (proprietario), g (gruppo), o (altri), a (tutti). Se non indichi una classe si assume a, con l'eccezione che i bit della umask non vengono toccati.
  • Operatori: + aggiunge bit, - li toglie, = imposta esattamente quei bit nella classe e azzera gli altri.

Quindi chmod u=rw,go=r notes.txt dà lo stesso risultato di chmod 644 notes.txt. chmod g+w notes.txt aggiunge la scrittura per il gruppo e lascia gli altri bit come sono.

L'ottale è compatto e facile da incollare negli script. La simbolica è più sicura per una modifica singola, perché non azzera bit a cui non hai pensato. In una revisione aspettati di trovarle entrambe, nei file di gestione della configurazione, nei Dockerfile e negli script di installazione.

chmod passo per passo

chmod cambia la modalità. Su un file, il comando riesce solo al proprietario o a root. Chiunque altro ottiene Operation not permitted.

Una buona abitudine è leggere la modalità, cambiarla e rileggerla:

bash
stat -c '%a %A %U:%G %n' notes.txt
chmod 600 notes.txt
stat -c '%a %A %U:%G %n' notes.txt

stat -c stampa la modalità ottale (%a), la modalità simbolica (%A), i nomi di proprietario e gruppo (%U, %G) e il nome del file (%n). Userai questo formato per tutto il lab.

chown cambia il proprietario e chgrp cambia il gruppo. Passare la proprietà a un altro utente di norma richiede root. Non eseguire chown -R su un albero finché non hai elencato cosa toccherà.

umask: modalità predefinite per i nuovi file

Quando un programma crea un file, chiede una modalità di partenza. Per un file normale il valore di partenza è 666. Per una directory è 777. La umask toglie bit da quel valore di partenza. La imposta la shell, e vale per ogni file e directory creati dalla shell e dai suoi figli.

La maggior parte delle distribuzioni Linux usa 022 come predefinito. Per un file, 666 meno 022 fa 644, quindi i nuovi file sono rw-r--r--. Per una directory, 777 meno 022 fa 755, quindi le nuove directory sono rwxr-xr-x. La umask toglie soltanto permessi. Una modalità non può mai risultare più permissiva del valore di partenza.

Controlla il tuo valore:

bash
umask

Una umask più severa come 077 dà file 600 e directory 700, accessibili solo al proprietario. Una più permissiva come 002 dà file 664 e directory 775, scrivibili dal gruppo. Una umask impostata in un profilo della shell influisce su quella shell e sui suoi figli. Non cambia i file che esistono già.

setuid, setgid e sticky bit

Le modalità ottali a quattro cifre aggiungono una cifra iniziale per tre bit speciali:

  • setuid (4000): quando un eseguibile parte, gira con l'ID utente del proprietario del file invece di quello del chiamante. Un binario di proprietà di root con setuid gira come root.
  • setgid (2000): su un eseguibile, gira con l'ID di gruppo del file. Su una directory, le nuove voci ereditano il gruppo della directory.
  • sticky (1000): su una directory, solo il proprietario di una voce o root può rinominarla o cancellarla, anche se tutti possono scrivere nella directory. /tmp è l'esempio classico.

ls -l mostra setuid come s nella posizione di esecuzione del proprietario, e sticky come t nella posizione di esecuzione degli altri. Su Ubuntu 24.04 la riga di passwd è questa:

text
-rwsr-xr-x 1 root root 64152 May 30  2024 /usr/bin/passwd

Programmi come passwd hanno bisogno di setuid perché devono scrivere file protetti degli account per conto di un utente normale. Il rischio è che ogni binario setuid di root permetta a un utente normale di eseguire codice con i diritti di root. Un bug in uno di questi, come una corruzione di memoria o una chiamata non sicura a un programma ausiliario, può diventare una privilege escalation locale. Chi fa revisioni tiene un elenco breve dei binari setuid e lo confronta con una baseline nota. Un nuovo file setuid che nessuno ha installato di proposito è un finding che richiede una risposta.

I file scrivibili da chiunque sono l'altro problema comune. Un file con o+w permette a qualsiasi account locale di cambiarne il contenuto. Se quel file è uno script, una configurazione letta da un servizio root o un binario in una directory del PATH, all'attaccante non serve un exploit. Gli basta modificare il file. Controlla anche le directory. Una directory scrivibile su un percorso eseguito da root può permettere a un attaccante di sostituire un file anche quando il file stesso è bloccato.

Lab pratico: file e permessi

Esegui tutto in un ambiente Linux che controlli tu: una distribuzione WSL o una VM creata per questo corso. Non farlo su un server di produzione o su una macchina condivisa. La sezione sul secondo utente crea un account, quindi falla solo nella tua VM di laboratorio.

Crea e ispeziona un file

bash
mkdir ~/permlab && cd ~/permlab
echo 'lab secret' > notes.txt && ls -l notes.txt

Su Ubuntu 24.04 sotto WSL, il nuovo file ha mostrato -rw-r--r-- con proprietario e gruppo chiamati come l'account. Il tuo nome utente, la data e il gruppo saranno diversi. Confronta la modalità.

Cambia la modalità

bash
chmod 600 notes.txt && stat -c '%a %U:%G %n' notes.txt
umask

Output osservato:

text
600 usurio:usurio notes.txt
0022

Il nome del tuo account sarà diverso. 600 significa che solo il proprietario può leggere e scrivere. 0022 è la umask nella shell corrente, e lo zero iniziale fa parte della forma ottale.

Ora una directory:

bash
mkdir sub && chmod 750 sub && stat -c '%a %n' sub

Risultato osservato: 750 sub. Il proprietario ha accesso completo, il gruppo può leggere ed entrare e gli altri utenti non hanno niente.

Modifiche simboliche, una alla volta, con una lettura dopo ciascuna:

bash
chmod u=rw,go=r notes.txt && stat -c '%a %A %n' notes.txt
chmod g+w notes.txt && stat -c '%a %A %n' notes.txt
chmod o-r notes.txt && stat -c '%a %A %n' notes.txt

Risultato osservato:

text
644 -rw-r--r-- notes.txt
664 -rw-rw-r-- notes.txt
660 -rw-rw---- notes.txt

Ogni comando ha cambiato solo i bit che indicava.

Guarda come la umask cambia i nuovi file

Esegui umask in una subshell, così la modifica non resta nella tua sessione:

bash
(umask 077; touch private.txt; stat -c '%a %A %n' private.txt)
(umask 002; touch shared.txt; mkdir made_dir; stat -c '%a %A %n' shared.txt made_dir)

Risultato osservato:

text
600 -rw------- private.txt
664 -rw-rw-r-- shared.txt
775 drwxrwxr-x made_dir

Con 077, il file ha perso tutti i bit di gruppo e degli altri. Con 002, il gruppo ha ottenuto la scrittura sia sul file sia sulla directory. La directory è partita da 777 e ha perso solo 002.

Prova l'accesso come secondo utente locale

Questo passo richiede un account che puoi creare nella tua VM. Eseguilo solo lì.

bash
sudo useradd -m labuser
sudo -u labuser cat ~/permlab/notes.txt

Non ho eseguito questi comandi. L'account WSL richiede una password per sudo e non l'ho inserita. Cosa cercare: con la modalità 600, il secondo comando dovrebbe fallire con un messaggio Permission denied, perché labuser non è né il proprietario né nel gruppo.

Poi allenta i permessi del file per gli altri:

bash
chmod 644 notes.txt
sudo -u labuser cat ~/permlab/notes.txt

Cosa cercare: il contenuto viene stampato solo se labuser può anche entrare nella tua home e in ~/permlab. Molte distribuzioni creano le home come 755, ma alcune usano 750. Se una directory superiore nega x agli altri utenti, la lettura fallisce comunque, anche con un file leggibile. Controlla con ls -ld ~ ~/permlab. Sull'installazione WSL di Ubuntu 24.04 che ho usato, ls -ld ~ ha stampato drwxr-x---, cioè 750, quindi lì un secondo utente sarebbe bloccato anche dopo chmod 644. In pratica è il bit x delle directory visto prima.

Cerca i permessi rischiosi

Elenca i file normali scrivibili da chiunque nella tua home, senza passare ad altri file system:

bash
find ~ -xdev -type f -perm -o+w 2>/dev/null

In un lab pulito non stampa niente. Per vedere la ricerca all'opera, rendi scrivibile un file di proposito:

bash
chmod 666 ~/permlab/notes.txt
find ~ -xdev -type f -perm -o+w 2>/dev/null
chmod 644 ~/permlab/notes.txt

Risultato osservato: la prima ricerca ha stampato /home/usurio/permlab/notes.txt. Dopo la correzione, la stessa ricerca non ha stampato niente.

Elenca i binari setuid in una directory di sistema:

bash
find /usr/bin -perm -4000 -type f 2>/dev/null | sort

Su Ubuntu 24.04 sotto WSL ha stampato dieci file, tra cui /usr/bin/passwd, /usr/bin/sudo, /usr/bin/su, /usr/bin/mount e /usr/bin/umount. Il tuo elenco dipende dalla distribuzione e dai pacchetti installati. In una revisione, confronta l'elenco con ciò che secondo il gestore di pacchetti dovrebbe essere setuid. Considera una voce inattesa una domanda a cui rispondere, non la prova di un attacco.

Controlla lo sticky bit sulle directory temporanee:

bash
stat -c '%a %A %n' /tmp /var/tmp

Risultato osservato: 1777 drwxrwxrwt per entrambe. La t significa che gli utenti possono creare file lì ma non cancellare quelli di qualcun altro.

Pulizia

bash
rm -rf ~/permlab
sudo userdel -r labuser

userdel -r cancella anche la home dell'account. Eseguilo solo per l'account di laboratorio che hai creato.

Cosa ha mostrato la prova su Windows

Gli stessi primi passi in Git Bash per Windows non si sono comportati come su Linux. Dopo chmod 600 notes.txt, stat riportava ancora 644, e nemmeno le chiamate chmod successive hanno cambiato l'output. Windows conserva i permessi nelle liste di controllo degli accessi NTFS, e Git Bash mappa solo alcuni bit. Un lab su Windows può insegnare i comandi, ma non può mostrare cosa fa una modalità Linux. Per questo articolo usa WSL con una distribuzione Linux, oppure una VM.

Errori comuni

Usare 777 per risolvere un errore di accesso negato. Funziona, e permette anche a tutti di scrivere ed eseguire il file. Trova quale classe viene bloccata e dai i permessi solo a quella.

Dimenticare la directory. Un file leggibile può restare irraggiungibile se a una directory superiore manca x per l'utente. Controlla ogni directory del percorso.

Usare chmod -R su un albero intero. Le modifiche ricorsive spesso mettono l'esecuzione sui file normali o la tolgono dalle directory. Usa find con -type f o -type d per colpire un solo tipo.

Fidarsi della modalità di un file copiato. cp, tar e gli strumenti di archiviazione possono mantenere o azzerare le modalità a seconda dei flag. Controlla il risultato con stat.

Leggere le modalità simboliche come assolute. chmod g+w aggiunge un bit. chmod g=w azzera lettura ed esecuzione per il gruppo. È una differenza che sfugge facilmente.

Ricorrere subito a root. Molti problemi di lettura e scrittura si risolvono con l'appartenenza a un gruppo o con la modalità di una directory, senza un programma ausiliario setuid o una shell di root.

Perché conta nelle revisioni di sicurezza

Una revisione dei permessi parte da una domanda: chi può cambiare ciò che un processo privilegiato legge o esegue? Tre finding tornano di continuo:

  1. File scrivibili su un percorso privilegiato. Una configurazione o uno script letti da un servizio root e scrivibili da un account normale sono un'escalation che aspetta solo una modifica.
  2. Binari setuid o setgid inattesi. Ognuno è codice che gira con più diritti di chi lo chiama. Confronta l'elenco con una baseline.
  3. Directory scrivibili in un percorso di ricerca o nella directory di un servizio. Un utente che può creare o rinominare un file lì può sostituire un file fidato, anche se il file stesso è bloccato.

Quando scrivi un finding, indica il percorso, la modalità, il proprietario, il gruppo, il processo che lo legge o lo esegue e la modifica che lo corregge. Prova nel tuo lab. Non eseguire queste ricerche su sistemi che non amministri, e non usare sudo -u sulla macchina di qualcun altro.

Per andare oltre

Quando le modalità di base sono chiare, studia le liste di controllo degli accessi con getfacl e setfacl, che aggiungono voci per singolo utente oltre a proprietario, gruppo e altri. Leggi il manuale di chattr per i flag immutable e append-only. Usa namei -l /path/to/file per stampare la modalità di ogni componente di un percorso. È il modo più rapido per trovare la directory che blocca un servizio.

Per le abitudini di shell dietro questi comandi, parti dall'articolo precedente del Manuale da campo sulle basi di Bash per studenti di sicurezza. L'articolo successivo, cos'è SSH e come funzionano le chiavi SSH, tratta le chiavi SSH, che dipendono dalle stesse modalità: il file della chiave privata deve essere leggibile solo dal suo proprietario, e un client SSH si rifiuta di usare una chiave con permessi troppo aperti.

Il privilegio minimo comincia dalle modalità dei file. Un processo che può scrivere meno fa meno danni quando sbaglia, e un file che gli altri non possono cambiare è una cosa in meno da controllare.

Fonti

Fonti

  1. GNU Coreutils manual: File permissions
  2. chmod(1) manual page, Linux man-pages
  3. umask(2) manual page, Linux man-pages
  4. chmod, POSIX.1-2024 utility specification (The Open Group)

Altro su Linux e strumenti per sviluppatori

Linux e strumenti per sviluppatori

Basi di Bash per il lavoro di sicurezza

Impara pipe, redirezioni, variabili, loop, codici di uscita e set -euo pipefail, poi usali per contare gli accessi falliti e calcolare l'hash di una cartella.

Base13 min di lettura

Linux e strumenti per sviluppatori

Chiavi SSH: come funzionano e come usarle in sicurezza

Come funzionano le chiavi host e utente di SSH, perché la scelta predefinita è Ed25519 con passphrase e come impostare un accesso con chiave e fare hardening su una VM di laboratorio tua.

Base11 min di lettura