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.
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.
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.
Ogni file e directory ha tre cose che decidono l'accesso:
Esegui questo comando su un file qualsiasi nella tua home:
ls -l notes.txtIl 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.
La modalità ha tre terne, una per ogni classe di utente:
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:
id
groupsUna modifica all'appartenenza a un gruppo di solito ha effetto al login successivo, non nella shell in cui hai eseguito il comando.
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.
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:
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.+ 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 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:
stat -c '%a %A %U:%G %n' notes.txt
chmod 600 notes.txt
stat -c '%a %A %U:%G %n' notes.txtstat -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à.
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:
umaskUna 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à.
Le modalità ottali a quattro cifre aggiungono una cifra iniziale per tre bit speciali:
/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:
-rwsr-xr-x 1 root root 64152 May 30 2024 /usr/bin/passwdProgrammi 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.
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.
mkdir ~/permlab && cd ~/permlab
echo 'lab secret' > notes.txt && ls -l notes.txtSu 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à.
chmod 600 notes.txt && stat -c '%a %U:%G %n' notes.txt
umaskOutput osservato:
600 usurio:usurio notes.txt
0022Il 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:
mkdir sub && chmod 750 sub && stat -c '%a %n' subRisultato 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:
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.txtRisultato osservato:
644 -rw-r--r-- notes.txt
664 -rw-rw-r-- notes.txt
660 -rw-rw---- notes.txtOgni comando ha cambiato solo i bit che indicava.
Esegui umask in una subshell, così la modifica non resta nella tua sessione:
(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:
600 -rw------- private.txt
664 -rw-rw-r-- shared.txt
775 drwxrwxr-x made_dirCon 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.
Questo passo richiede un account che puoi creare nella tua VM. Eseguilo solo lì.
sudo useradd -m labuser
sudo -u labuser cat ~/permlab/notes.txtNon 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:
chmod 644 notes.txt
sudo -u labuser cat ~/permlab/notes.txtCosa 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.
Elenca i file normali scrivibili da chiunque nella tua home, senza passare ad altri file system:
find ~ -xdev -type f -perm -o+w 2>/dev/nullIn un lab pulito non stampa niente. Per vedere la ricerca all'opera, rendi scrivibile un file di proposito:
chmod 666 ~/permlab/notes.txt
find ~ -xdev -type f -perm -o+w 2>/dev/null
chmod 644 ~/permlab/notes.txtRisultato 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:
find /usr/bin -perm -4000 -type f 2>/dev/null | sortSu 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:
stat -c '%a %A %n' /tmp /var/tmpRisultato osservato: 1777 drwxrwxrwt per entrambe. La t significa che gli utenti possono creare file lì ma non cancellare quelli di qualcun altro.
rm -rf ~/permlab
sudo userdel -r labuseruserdel -r cancella anche la home dell'account. Eseguilo solo per l'account di laboratorio che hai creato.
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.
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.
Una revisione dei permessi parte da una domanda: chi può cambiare ciò che un processo privilegiato legge o esegue? Tre finding tornano di continuo:
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.
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.
Linux e strumenti per sviluppatori
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.
Linux e strumenti per sviluppatori
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.
Linux e strumenti per sviluppatori
GitHub spiegato a chi comincia: che cosa fanno Git e GitHub, i termini che ti servono, una prova locale con Git e come controllare un progetto prima di eseguirlo.