Sicurezza Directory · 11 min read · Jan 10, 2026
Creare una directory sicura con PAM e EncFS
Creare una directory sicura con PAM e EncFS
Contenuti
. Introduzione
. Installazione di encfs
. Installazione di pam_script
. Regolazione della configurazione PAM
. Il risultato
Introduzione
Lavoro molto con programmi che richiedono credenziali
Esempi di questi programmi sono:
. mount.cifs
. fusesmb (cerca dettagli qui)
Ora, nella mia rete (e in altre) le credenziali fornite al login potrebbero (e dovrebbero) essere utilizzate da questi programmi. Come puoi recuperare queste credenziali, fornendo abbastanza sicurezza?
Con i moduli PAM pam_script è possibile memorizzare la password in un file, che sarà utilizzato da fusemb e mount.cifs per leggere la password.
Per ottenere sicurezza, si potrebbe rendere l’utente che effettua il login proprietario e negare la lettura/scrittura a chiunque altro. Rimuovi questo file quando l’utente termina la sua sessione.
Questo è sufficiente, per il runtime. Ma mi chiedevo, ma cosa succede se il sistema si blocca e il file con le credenziali rimane sull’hard disk? Chiunque sia in grado di montare questo hard disk con ad esempio un lifecd, può leggere questo file!
Ecco perché stavo cercando un modo per crittografare questo file.
Con encfs questo è molto possibile! A tempo di esecuzione fornisce un’interfaccia per file e directory crittografati, che esistono solo a tempo di esecuzione! Quando il sistema non è in esecuzione, ci sono solo file crittografati, inutili se non conosci la chiave. E questa chiave è esattamente la password (crittografata)! Ecco perché ho scelto una combinazione di PAM e Encfs.
Cerca il sito web di Encfs: http://freshmeat.net/projects/encfs
Questa costruzione è destinata a fornire abbastanza sicurezza per il runtime e il downtime (dopo un crash) per memorizzare informazioni sensibili, non per creare una directory sicura permanente sul tuo hard disk per memorizzare documenti.
Installazione di encfs
Certo FUSE deve essere installato.
L’installazione è molto semplice:
(guarda il sito web per rlog che è richiesto da EncFs)
tar -xzf encfs-*.tar.gz
cd encfs-*
configure --prefix=/usr --sysconfdir=/etc --libexecdir=/usr/sbin
make
make installDopo l’installazione puoi testare se funziona:
mkdir -p ~/test/encrypted
mkdir -p ~/test/decrypted
encfs ~/test/encrypted ~/test/decrypted
mount (dovrebbe mostrare il mount appena creato)
echo "Questo è molto segreto." > ~/test/decrypted/testfileLa directory encrypted contiene i file crittografati e rimane sull’hard disk dopo il smontaggio e/o lo spegnimento. La directory decrypted è l’interfaccia a essa e scompare quando viene smontata e/o spenta.
Il file testfile dovrebbe apparire nella directory decrittografata e in forma crittografata nella directory crittografata. Nome e contenuto del file sono crittografati.
Ho scelto una mappa separata nella macchina locale dove per ogni utente che effettua il login verrà memorizzato un crittografato (e un’interfaccia a esso):
install -m777 -o root -g root /var/lib/encfsNota i permessi: tutti devono essere in grado di creare una directory qui. Più avanti in questo documento viene spiegato perché.
Installazione di pam_script
L’installazione è molto semplice. Dopo un comando make sposta la libreria nella directory appropriata, /lib/security.
tar -xzf pam-script-*.tar.gz
cd pam-script-*
make
mv pam_script.so /lib/security
chown root:root /lib/security/pam_script.so
chmod 755 /lib/security/pam_script.soPam_script.so utilizza alcuni parametri. Tutti sono descritti nel README nella directory sorgente. Importanti sono:
parametri comuni
- runas=#user# : fa sì che lo script venga eseguito come utente #user#
parametri solo nella parte di autenticazione
- onauth=/path/to/onauth/script : percorso dello script che viene eseguito quando nella parte di autenticazione
predefinito è /etc/security/onauth
solo nella parte di sessione
onsessionopen=/path/to/onsessionopen/script : percorso dello script che viene eseguito quando viene avviata una sessione (valida)
predefinito è /etc/security/onsessionopenonsessionclose=/path/to/onsessionclose/script : percorso dello script che viene eseguito quando una sessione viene chiusa
predefinito è /etc/security/onsessionclose
Dopo l’installazione, la cosa più complessa è configurare il sistema per utilizzare questo modulo.
Regolazione della configurazione PAM
Ho usato pam_script nella parte di autenticazione e nella parte di sessione del file di servizio pam (login,kde).
Prima descrivo come regolare la parte di autenticazione, dove pam_script è usato più di una volta.
La parte di autenticazione
Pam_script ha la capacità (dalla versione 0.1.5) di ottenere la password fornita al login e renderla disponibile agli script tramite una variabile di ambiente PAM_AUTHTOK.
Lo scopo qui è creare una directory sicura dove vengono memorizzate informazioni riservate (come credenziali).
Il modulo è impilato nella parte di autenticazione:
cat /etc/pam.d/login-- snip --
auth required pam_shells.so
auth required pam_script.so expose=1
auth sufficient pam_unix.so use_first_pass
auth sufficient pam_ldap.so use_first_pass
auth required pam_script.so onauth=/etc/security/onauth.failed
auth required pam_deny.soCome puoi vedere, uso pam_scripts.so più volte:
La prima volta per eseguire uno script che crea una directory crittografata (con encfs) e per scrivere la password segreta in un file in questa directory per l’uso da parte di programmi sensibili alle credenziali come fusesmb e mount.cifs. Questo viene fatto appena prima del primo modulo di autenticazione successivo, pam_unix.
L’ultima volta per eseguire uno script quando l’autenticazione non ha avuto successo. Quando i moduli di autenticazione precedenti falliscono (pam_unix e pam_ldap) (e solo allora) questo modulo viene raggiunto. È necessario smontare la directory crittografata e rimuovere i file temporanei.
Nota che l’ultimo modulo di tutti è pam_deny, è davvero necessario. Senza di esso, chiunque può effettuare il login. Questo perché pam_script restituisce sempre “PAM_SUCCESS”, indipendentemente dal valore di ritorno degli script.
Non dimenticare di aggiungere il flag “use_first_pass” al modulo esistente pam_unix.so.
Gli script
cat /etc/security/onauth#!/bin/bash
retcode=0;
userid=$1
service=$2
authtok=$3
if [ -z "$authtok" ]; then
authtok=$PAM_AUTHTOK
fi;
userproperties=$(getent passwd | grep -m 1 -E "^$userid")
if [ -z "$userproperties" ]; then
#
# userproperties non trovati: qualcosa non va
#
echo "Utente non trovato."
exit
fi;
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);
if [ -d /var/lib/encfs ]; then
# crea un sicuro
if [ ! -d /var/lib/encfs/$userid ]; then
install -m700 -o $uidnr -g $gidnr -d /var/lib/encfs/$userid
fi;
if [ ! -d /var/lib/encfs/$userid/encrypted ]; then
install -m700 -o $uidnr -g $gidnr -d /var/lib/encfs/$userid/encrypted
fi;
if [ ! -d /var/lib/encfs/$userid/unencrypted ]; then
install -m700 -o $uidnr -g $gidnr -d /var/lib/encfs/$userid/unencrypted
fi;
if [ ! -d /var/lib/encfs/$userid/run ]; then
install -m700 -o $uidnr -g $gidnr -d /var/lib/encfs/$userid/run
fi;
#
# testare se la directory crittografata non è già montata
#
if [ -z "$(mount | grep -w /var/lib/encfs/$userid/unencrypted )" ]; then
#
# crea un programma di fornitura della password
#
cd /var/lib/encfs/$userid
md5authsum=$(echo $authtok | md5sum | cut -d " " -f 1)
echo "$md5authsum" > run/tmp
echo "$md5authsum" >> run/tmp
chown $uidnr:$gidnr run/tmp
rm -rf encrypted/*
rm -f encrypted/.encfs*
cat run/tmp | encfs -S /var/lib/encfs/$userid/encrypted /var/lib/encfs/$userid/unencrypted -- -o allow_root 1>>/dev/null
fi;
#
# questo è ciò di cui si tratta: memorizzare le credenziali in un file
# in questo caso la password
#
if [ -n "$(mount | grep -w /var/lib/encfs/$userid/unencrypted )" ]; then
cd /var/lib/encfs/$userid/unencrypted/
if [ -f password.tmp ]; then
rm password.tmp
fi;
echo $authtok > password.tmp
fi;
fi;
Alcune osservazioni:
Questo script crea una directory crittografata (se non esiste già) con encfs. Nota l’opzione -S in encfs: la password per questa directory crittografata viene letta da stdin e non viene richiesta.
Questa password è la stessa usata al login.
La directory crittografata si trova in /var/lib/encfs/$userid.
La password viene scritta in un file, password.tmp. Questo è un file temporaneo: la password non deve essere quella corretta. Più avanti nel processo, a seconda del successo della validazione, questo file viene rinominato (in password) o rimosso.
È molto importante notare che lo script viene eseguito come l’utente che effettua il login, non come root! E poiché programmi come mount.cifs devono successivamente avere accesso a questa directory per leggere il file della password, viene aggiunta l’opzione fuse comune allow_root.
#!/bin/bash
userid=$1
service=$2
userproperties=$(getent passwd | grep -m 1 -E "^$userid")
if [ -z "$userproperties" ]; then
#
# userproperties non trovati: qualcosa non va
#
echo "Utente non trovato."
exit
fi;
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);
#
# questo script viene eseguito quando l'autenticazione fallisce
# un sicuro crittografato viene comunque creato
# quindi è importante rimuovere questo sicuro di nuovo
#
if [ -d /var/lib/encfs ]; then
if [ -d /var/lib/encfs/$userid/unencrypted ]; then
#
# testare se la directory crittografata è già montata
#
if [ -n "$(mount | grep -w /var/lib/encfs/$userid/unencrypted )" ]; then
if [ $(w -h $userid | wc -l) -eq 0 ]; then
#
# questo utente non è connesso su più tty
# rimuovi tutto e smonta la directory crittografata
#
rm -rf /var/lib/encfs/$userid/unencrypted/*
fusermount -u /var/lib/encfs/$userid/unencrypted
rm -rf /var/lib/encfs/$userid/encrypted/*
rm -f /var/lib/encfs/$userid/encrypted/.encfs*
else
#
# questo utente è ancora connesso
#
rm -f /var/lib/encfs/$userid/unencrypted/password.tmp
fi;
fi;
if [ -z "$(mount | grep -w /var/lib/encfs/$userid/unencrypted )" ]; then
rm -rf /var/lib/encfs/$userid/encrypted/*
rm -f /var/lib/encfs/$userid/encrypted/.encfs*
rm -rf /var/lib/encfs/$userid/unencrypted/*
fi;
fi;
fi;
Alcune osservazioni:
Questo script viene eseguito quando le credenziali fornite non sono valide. La directory crittografata, che è stata appena impostata, verrà rimossa (smontata) e svuotata. Questo avviene ovviamente solo quando questo utente non è connesso su alcun altro tty.
La parte di sessione
Quando si raggiunge la parte di sessione, è certo che le credenziali fornite (password) siano corrette. Questo significa che la password - nella fase di autenticazione memorizzata in un file temporaneo - è corretta. Quindi una cosa da fare nella fase di sessione è spostare il contenuto di password.tmp in quello permanente, password.
Una seconda cosa è eseguire script che necessitano di queste credenziali per il proprio uso, come il montaggio di condivisioni CIFS o fusesmb.
È logico che qualsiasi informazione riservata rimanga all’interno della directory sicura. Questo era ciò di cui si trattava in primo luogo!!
Nota che questo modulo esegue due script per impostazione predefinita:
. /etc/security/onsessionopen: quando una sessione inizia/apre;
. /etc/security/onsessionclose: quando una sessione termina/chiude.
Seguo il predefinito, non c’è motivo di fare diversamente.
Il mio file /etc/pam.d/login (la parte di sessione) appare così:
cat /etc/pam.d/login-- snip --
session required pam_mkhomedir.so
session required pam_motd.so
session optional pam_mail.so empty dir=/var/mail
session optional pam_lastlog.so
session required pam_env.so
session required pam_script.so
session required pam_unix.so
session required pam_ldap.soGli script
All’apertura della sessione
cat /etc/security/onsessionopen#!/bin/bash
retcode=0;
userid=$1
service=$2
userproperties=$(getent passwd | grep -E "^$userid")
if [ -z "$userproperties" ]; then
#
# userproperties non trovati: qualcosa non va
#
echo "Utente non trovato."
exit
fi;
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);
if [ -d /var/lib/encfs/$userid/encrypted ]; then
#
# testare se la directory crittografata è montata
#
if [ -n "$(mount | grep -w /var/lib/encfs/$userid/unencrypted )" ]; then
if [ -f /var/lib/encfs/$userid/unencrypted/password.tmp ]; then
if [ -f /var/lib/encfs/$userid/unencrypted/password ]; then
#
# un vecchio file di password trovato
#
if [ -z "(diff /var/lib/encfs/$userid/unencrypted/password /var/lib/encfs/$userid/unencrypted/password.tmp)" ]; then
#
# nuova password e quella vecchia sono le stesse
#
rm /var/lib/encfs/$userid/unencrypted/password.tmp
else
mv /var/lib/encfs/$userid/unencrypted/password.tmp /var/lib/encfs/$userid/unencrypted/password
fi;
else
#
# password non trovata : è il primo login.
# semplicemente sposta il file di password temporaneo in quello rimanente
#
mv /var/lib/encfs/$userid/unencrypted/password.tmp /var/lib/encfs/$userid/unencrypted/password
fi;
fi;
if [ -d /etc/session.d/pam/onsessionopen ]; then
for script in /etc/session.d/pam/onsessionopen/*.sh; do
if [ -x $script ]; then
eval $script $userid $service
fi
done;
fi;
fi;
fi;
Alla chiusura della sessione
cat >> /etc/security/onsessionclose#!/bin/bash
userid=$1
service=$2
userproperties=$(getent passwd | grep -E "^$userid")
if [ -z "$userproperties" ]; then
#
# userproperties non trovati: qualcosa non va
#
echo "Utente non trovato."
exit
fi;
homedir=$(echo $userproperties | cut -d ":" -f 6);
gidnr=$(echo $userproperties | cut -d ":" -f 4);
uidnr=$(echo $userproperties | cut -d ":" -f 3);
#
# questo script viene eseguito quando l'autenticazione fallisce
# un sicuro crittografato viene comunque creato
# quindi è importante rimuovere questo sicuro di nuovo
#
if [ -d /var/lib/encfs ]; then
if [ -d /var/lib/encfs/$userid/unencrypted ]; then
#
# testare se la directory crittografata è già montata
#
if [ -n "$(mount | grep -w /var/lib/encfs/$userid/unencrypted )" ]; then
if [ $(w -h $userid | wc -l) -eq 0 ]; then
rm -rf /var/lib/encfs/$service.$userid/unencrypted/*
fusermount -u /var/lib/encfs/$userid/unencrypted
rm -rf /var/lib/encfs/$userid/encrypted/*
rm -f /var/lib/encfs/$userid/encrypted/.encfs*
fi;
else
rm -rf /var/lib/encfs/$userid/encrypted/*
fi;
if [ -d /etc/session.d/pam/onsessionclose ]; then
for script in /etc/session.d/pam/onsessionclose/*.sh; do
if [ -x $script ]; then
eval $script $userid $service
fi
done;
fi;
fi;
fi;Alcune osservazioni:
. importante: le versioni precedenti di shadow (dove il programma di login è parte di) non chiudevano le sessioni per impostazione predefinita (versioni precedenti alla 4.0.12). Dovrai aggiungere:
CLOSE_SESSIONS yesal file /etc/login.defs.
Questa opzione non è documentata e non è presente nel file login.defs installato dal pacchetto Shadow. Dovrai aggiungerla tu stesso.
Nelle versioni più recenti questa opzione è stata rimossa: la sessione viene sempre chiusa.
Il risultato
La directory crittografata contiene ora le credenziali, che sono disponibili solo per il proprietario e root. Creando un file mount.cifs.conf con questi valori:
touch /var/lib/encfs/$userid/unencrypted/mount.cifs.conf
chmod 600 /var/lib/encfs/$userid/unencrypted/mount.cifs.conf
echo "username=$userid" > /var/lib/encfs/$userid/unencrypted/mount.cifs.conf
echo -n "password=" >> /var/lib/encfs/$userid/unencrypted/mount.cifs.conf
cat /var/lib/encfs/$userid/unencrypted/password >> /var/lib/encfs/$userid/unencrypted/mount.cifs.confOra è possibile montare una condivisione cifs con:
/sbin/mount.cifs //fileserver/public /home/sbon/netshares/fileserver/public -o credentails=/var/lib/encfs/sbon/unencrypted/mount.cifs.conf,ip=192.168.0.2dove la directory /home/sbon/netshares/fileserver/public esiste, e c’è una condivisione “public” disponibile su “fileserver”, un server smb/cifs con numero ip 192.168.0.2.
Questo comando deve essere eseguito come root. Root deve avere accesso alla directory crittografata.
Un altro esempio è fusesmb, che può utilizzare le credenziali per navigare nel vicinato di rete smb. Questo non viene fatto creando un file separato solo per le credenziali, ma nel file di configurazione globale-per-utente di fusesmb in ~/.smb/fusesmb.conf:
(qui creo un semplice file di configurazione con solo credenziali)
touch /var/lib/encfs/sbon/unencrypted/fusesmb.conf
chmod 600 /var/lib/encfs/sbon/unencrypted/fusesmb.conf
echo "[global]" > /var/lib/encfs/sbon/unencrypted/fusesmb.conf
echo "username = sbon" >> /var/lib/encfs/sbon/unencrypted/fusesmb.conf
echo -n "password = " >> /var/lib/encfs/sbon/unencrypted/fusesmb.conf
cat /var/lib/encfs/sbon/unencrypted/password >> /var/lib/encfs/sbon/unencrypted/fusesmb.conf
ln -sf /var/lib/encfs/sbon/unencrypted/fusesmb.conf /home/sbon/.smb/fusesmb.conf
L’ultimo link è perché fusesmb (avviato da sbon) si aspetta che il file di configurazione sia lì.
Ora avvialo con:
fusesmb /home/sbon/networkquando sono connesso come me stesso (sbon). La directory /home/sbon/network deve esistere.
Ricevi i nuovi post nella tua casella di posta.
Nessuno spam. Disiscriviti in qualsiasi momento.