blog:detection_d_intrusion_avec_mtree_8_et_etc_security

Détection d'intrusion avec mtree(8) et /etc/security

Sur NetBSD, sauf modification de l'administrateur, ce dernier reçoit tous les matins un message le renseignant sur la sécurité de son système. Ce message est généré par le script /etc/security (cf. security.conf(5)) et est lancé par /etc/daily (cf /etc/daily et ses amis). Parmi les outils utilisés dans security, se trouve mtree(8) (sauf modification ie. sauf si check_mtree=NO dans /etc/security.conf, ce qui n'est pas le cas par défaut).

Notion de spécification

D'après la page de manuel de mtree(8) (traduction approximative), le format du fichier de spécification est le suivant :

  • les lignes commençant par un # sont des commentaires
  • une ligne commençant par /set indique des paramètres par défaut ; s'ensuivent les paramètres param=value ; l'espace est séparateur
  • on peut supprimer des paramètres avec une ligne commençant par /unset ; s'ensuivent les paramètres param ; l'espace est séparateur
  • les lignes de spécifications de fichiers proprement dites ; elles consistent en :
    1. un chemin qui peut contenir les caractères spéciaux [, ], ? et *
    2. les couples param=value sont séparés entre eux par des espaces par contre, il n'y a pas d'espace de part et d'autre du signe égal =

Le premier chemin doit être un répertoire nommé . pour s'assurer que le mélange entre chemins relatifs et absolus sera consistant. De plus les répertoires intermédiaires doivent être mentionnés. Si deux lignes indiquent des paramètres différents pour un même chemin, la dernière prend le pas sur les précédentes (last match, voir aussi l'option -M).

Un chemin contenant un / sera considéré comme un chemin absolu même s'il n'est pas le premier caractère. Tous les répertoires parents doivent exister.

Créer une spécification

$ mtree -c -K sha1 -p /usr/local > /tmp/local.tmp
$ mtree -C -f /tmp/local.tmp > /tmp/local.mtree
  • -c → création,
  • -C → reformatage avec sortie plus facile à parser,
  • -K sha1,rmd160 → on veut « aussi » (en plus des paramètres standard) les sommes de contrôles SHA1,
  • -p /usr/local → le répertoire,
  • -f … → la spécification.

Vérifier une arborescence

$ touch /usr/local/plop
$ mtree -p /usr/local -f /tmp/local.mtree
.:      modification time (Tue Jul 19 02:27:40 2011, Tue Jul 19 13:22:06 2011)
extra: plop
  • -p … le répertoire à vérifier,
  • -f … le fichier de spécification.

Pour restaurer les droits et propriétés d'une arborescence, utiliser l'option -U :

$ mtree -p /usr/local -f /tmp/local.mtree -U
...

Après restauration d'une sauvegarde, cela s'avère très pratique.

Fichier de spécifications

Pour commencer, se souvenir que security gère avec RCS les fichiers listés dans /etc/mtree/special et /etc/mtree/special.local (et /etc/changelist). On ne veut pas voir certaines informations contenues dans ces fichiers transiter par courrier électronique, mêmes perdues dans un diff(1) : mots de passe, clefs de chiffrement, etc.

Ajouter tags=nodiff pour toutes les lignes spécifiant des fichiers contenant des clefs de chiffrement et des mots de passe. Dès lors, aucun diff(1) ne sera fait et ainsi le contenu n'apparaîtra pas en clair (dans un message électronique en clair ou un journal mais sécurisé).

Sur un système NetBSD 5.1, par défaut il y a dans /etc/mtree/special :

./etc/ipsec.conf                type=file mode=0600 optional tags=nodiff
./etc/master.passwd             type=file mode=0600 tags=nodiff
./etc/ssh/ssh_host_dsa_key      type=file mode=0600 optional tags=nodiff
./etc/ssh/ssh_host_key          type=file mode=0600 optional tags=nodiff
./etc/ssh/ssh_host_rsa_key      type=file mode=0600 optional tags=nodiff
./etc/racoon/psk.txt            type=file mode=0600 optional tags=nodiff
./root/.ssh/id_dsa              type=file mode=0600 optional tags=nodiff
./root/.ssh/id_rsa              type=file mode=0600 optional tags=nodiff
./root/.ssh/identity            type=file mode=0600 optional tags=nodiff

Soit un second fichier /usr/local/etc/exclude_diff contenant par exemple :

/etc/openssl/private
/usr/pkg/etc/httpd/ssl.key
/root/.my.cnf

pour permettre d'ajouter sur les lignes idoines tags=nodiff (avec grep -v -f … et grep -f …).

Le script suivant génère /etc/mtree/special.local (adapter $check_dirs) :

#!/bin/ksh
#
# $Id: gen_special_local.sh,v 1.18 2011/07/20 20:07:18 pc Exp pc $
export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/pkg/bin:/usr/pkg/sbin
 
check_dirs="/etc /usr/pkg/etc /root /usr/local/etc \
        /var/cron /var/at /var/db /var/spool/sockets /var/spool/clientmqueue /var/spool/mqueue /var/yp \
        /var/www/htdocs/www/cgi-bin ..."
tmp=/root/tmp
 
umask 0077
mkdir -p ${tmp}
 
# mtree(8) needs all parents dir. in specification
function head_dir {
        dir=$(dirname ${1})
 
        while [[ $(echo $dir | cut -d '/' -f 2) != "" ]]; do
                echo ".${dir} type=dir"
                dir=$(dirname $dir)
        done
}
 
grep 'tags=nodiff' /etc/mtree/special | awk '{ print $1 }' > ${tmp}/nodiff
cat /usr/local/etc/exclude_diff >> ${tmp}/nodiff
 
for d in ${check_dirs}; do
        special=$(echo ${d} | sed -e 's/^\///; s/\//_/g')
        mtree -c -K all,sha1 -X /usr/local/etc/exclude_all_patterns -p ${d} |\
                mtree -C -K uname,gname,type,nlink,mode,sha1 -R time,size,flags |\
                sed -e "s,^\.,.${d}," > ${tmp}/${special}.mtreeX \
                        && rm -f ${tmp}/${special}.tmp
        head_dir ${d} | sort > ${tmp}/${special}.mtree
        # diff
        grep -v -f ${tmp}/nodiff ${tmp}/${special}.mtreeX >> ${tmp}/${special}.mtree
        # nodiff
        grep -f $tmp/nodiff $tmp/${special}.mtreeX | \
                sed -e 's/$/ tags=nodiff/' >> ${tmp}/${special}.mtree && rm -f ${tmp}/${special}.mtreeX
done
 
cat > ${tmp}/special.local <<EOF
# $(date)
# $(hostname)
 
# /
/set type=file
. type=dir uname=root gname=wheel
EOF
cat ${tmp}/*.mtree >> ${tmp}/special.local && rm -f ${tmp}/*.mtree

L'administrateur système consciencieux chiffre et/ou signe les spécifications et surtout les enregistre sur une autre machine (avec la signature).

Signature

On signe le fichier en clair avec :

$ gpg --clearsign special.local

mais le fichier est alors modifié et n'est donc plus valide pour mtree(8) ; mieux vaut donc une signature détachée :

$ gpg -a -b special.local

Dans les deux cas, on le vérifie avec :

$ gpg --verify special.local.asc

Vérifier l'arborescence

$ sudo mtree -f /root/tmp/special.local |egrep -v "^(extra|missing):"

Pour une utilisation via /etc/daily et /etc/security :

  1. s'assurer que check_mtree=YES est présent dans /etc/security.conf,
  2. que le script est bien lancé par cron(8),
  3. que la sortie pourra bien être délivrée (MSA/MDA ou autre).

Dès qu'on doit gérer plusieurs machines, on a tout intérêt à lancer /etc/daily à distance via SSH pour capturer la sortie sur les différents systèmes. La sortie du script security est gérée et envoyée par courrier électronique dans daily ; commenter les quelques lignes kivonbien pour intégrer la sortie de security et security.local à l'ensemble. On n'a alors plus qu'un seul (gros) rapport à lire le matin.

Rien n'empêche non plus de chiffrer et/ou signer les rapports avant de les envoyer ou de les stocker.

  • blog/detection_d_intrusion_avec_mtree_8_et_etc_security.txt
  • Dernière modification : 2011/09/06 06:39
  • de pc