Par Steve O'Neil
Vous trouverez ci-dessous deux scripts, l'un sous shell, l'autre sous awk, permettant de trouver tous les fichiers de votre système possédant les mêmes numéros d'i-noeuds. Pourquoi est-il nécessaire de savoir ça ? Eh bien, il y a trois raisons qui me viennent à l'esprit.
En premier lieu, il est souvent utile, lorsque vous gérez un système, de savoir où se trouvent tous les fichiers liés. Étant donné qu'un i-noeud sous Linux n'est libéré que lorsque le dernier lien est enlevé, il peut être utile de savoir combien de fichiers doivent être supprimés pour pouvoir vraiment effacer un fichier donné.
En second lieu, connaître tous les liens (hard links) de votre système peut être utile dans le cas d'une intrusion. Supposons que quelqu'un s'insinue dans votre système et installe un détecteur de paquets, un détecteur de mouvement de touches de clavier, ou quelqu'autre chose pas très sympathique. S'il veut être sûr de pouvoir continuer son travail même si vous avez repéré son programme, il peut simplement créer des liens (hard links) vers ce dernier dans quelques endroits reculés du système. Alors, même si vous trouvez le programme initial et que vous l'effacez, il peut simplement le redémarrer sous l'un des autres noms de fichier qu'il a créés, en supposant qu'il puisse toujours accéder à votre système. Cependant, si vous examinez l'i-noeud du programme initial et que vous exécutiez l'un de ces scripts, vous verrez apparaître tous les liens vers ce fichier. Bien sûr, vous pouvez obtenir la même chose en utilisant "find", si vous connaissez le numéro d'i-noeud que vous recherchez, mais vous n'obtiendrez pas d'informations sur l'ensemble des liens de votre système, et ceci m'a conduit à écrire ces scripts ...
Si vous voulez avoir une approche proactive de la sécurité de votre système, vous effectuerez un tas d'essais sur les fichiers, ainsi que des examens, pour vous préserver d'une intrusion. Si vous utilisez ces scripts sur votre système, en étant sûr qu'il n'est pas corrompu, et que vous gardez une liste des liens qui sont sûrs, vous pourrez effectuer une vérification périodique de votre système, par exemple une fois par jour, et vous comparerez la nouvelle liste des liens avec celle d'origine. Si une différence apparait, plus spécialement dans les répertoires "systèmes", tels que /bin, /lib, /etc et autres, vous serez averti immédiatement.
Les scripts devraient fonctionner sur tout système possédant bash ou zsh,
et la plupart des distributions Linux fournissent une version de awk. Le
mécanisme d'affichage repose cependant sur l'utilisation du programme ls
amélioré de Mark Baranowski et James Gleason, qui s'appelle els
. À la
différence de ls
, els
vous permet d'avoir le contrôle complet sur le
format d'affichage des fichiers. C'est un programme étonnant et je vous
invite à l'utiliser, même si vous n'utilisez pas mes scripts. Son seul
inconvénient est qu'il n'affiche pas les différents types de fichiers en
plusieurs couleurs, mais c'est un défaut mineur en comparaison de la
puissance du programme. Il est disponible par ftp sur
ftp://perseus.elen.utah/pub/markb/els.tar.Z. La version actuelle est la 1.44.
Vous trouverez les scripts ci-dessous. Vous pouvez adapter la liste des répertoires dans "findharlinks.sh" suivant vos préférences, et modifier l'endroit où se trouve l'interpréteur awk dans "showsame.awk" suivant votre configuration.
Pour les utiliser, tapez tout d'abord "findhardlinks" sur la ligne de commande, en tant que root. Un fichier appelé "allfiles.lstsrt" sera créé dans /temp (ou tout autre répertoire que vous aurez choisi). Soyez patient; si vous avez beaucoup de fichiers et de répertoires, cela prendra quelques minutes. Quand c'est terminé, copiez "showsame.awk" dans le même répertoire que "alfiles.lst.srt" et tapez
showsame.awk allfiles.lst.srt
Cela créera un fichier appelé "outfile.txt", contenant la liste des fichiers ayant des liens communs. Pour éliminer les lignes en double, utilisez "uniq" comme ceci:
uniq outfile.txt > outfile.nodup
et vous en avez terminé. Le fichier "outfile.nodup" contient la liste des liens que vous recherchez. Bien sûr, j'aurais pu tout mettre dans un seul gros script, mais je voulais vous montrer comme les différents ensembles fonctionnent. Vous êtes libres d'assembler et de configurer ces scripts comme bon vous semble.
Un dernier point: les liens entre fichiers n'ont de signification que sur le même système de fichiers, aussi lorsque vous mettez votre liste de répertoires dans le script, soyez certains qu'ils font partie du même système de fichiers, tel que "/".
findhardlink.sh
# Ces répertoires se trouvent tous sous "/" sur mon système; vous pouvez
# modifier cette liste selon votre configuration
for i in bin boot etc home lib opt root sbin tmp usr var
do
# Cette ligne génère un listing se rapportant à tous les répertoires
# spécifiés, ainsi que leurs sous-répertoires, et donne tous les numéros
# d'i-noeud de chaque fichier, ainsi que le chemin complet, et place l'ensemble
# dans "allfiles.lst".
els -a -i +R +NF $i >> /temp/allfiles.lst
done
cd /temp
sort allfiles.lst > allfiles.lst.srt
rm allfiles.lst
showname.awk
#! /usr/bin/awk -f
BEGIN {
getline #va à la première ligne du fichier, puis
n1=split($0, test1) #place les champs dans un tableau, puis
#incrémente le pointeur
}
{
# voici la boucle de comparaison des i-noeuds
n2=split($0, test2) #place la ligne suivante dans un tableau
if (test1[1] == test2[1]) { #regarde si les numéros d'i-noeud des deux
#lignes ont le même champ 1 dans les deux
#chaînes
# s'ils sont identiques, affiche le contenu des deux
for (i=1; i <= n1; i++) {
printf ("%s ", test1[i]) >> "outfile.txt"
} #notez l'espace après %s; cela
#inclut des retours chariot
#entre les champs perdus
#lorsque les chaînes sont
#interrompues dans les tableaux
printf ("\n") >> "outfile.txt"
for (i=1; i <= n2; i++) {
printf ("%s ", test2[i]) >> "outfile.txt"
}
printf ("\n") >> "outfile.txt"
}
#Place maintenant la chaîne la plus récente dans le tableau contenant la
#chaîne précédente; ceci permet la comparaison entre chaque ligne et celle
#qui la précède.
for (i=1; i <= n2; i++) {
test1[i] = test2[i]
}
n1 = n2 #positionne le nombre de champs du tableau qui contient
#maintenant de ce qui est devenu la chaîne précédente
#au nombre de champs dans cette chaîne
next #va rechercher la chaîne suivante et recommence
}
Copyright © 1999, Steve O'Neil. Publié dans le n° 44 de Linux Gazette, Août 1999.
Traduction française de Jacques Chion.