Snort Inline — Première partie

Gazette Linux n°117 — Août 2005

Pete Savage

Article paru dans le n°117 de la Gazette Linux d'août 2005.

Traduction française par Deny .

Relecture de la traduction française par Joëlle Cornavin .

Article publié sous Open Publication License. La Linux Gazette n'est ni produite, ni sponsorisée, ni avalisée par notre hébergeur principal, SSC, Inc.


Table des matières
1. Introduction
2. Configuration initiale
3. Test de snort_inline
4. Retour de votre système à la normale
5. Programme des réjouissances

1. Introduction

L'intrusion de réseau est un aspect important de la sécurité réseau. Il y a une grande variété d'IDS (Intrusion Detection Systems, systèmes de détection d'intrusion) disponibles actuellement. Bien qu'ils soient extrêmement utiles pour recueillir des informations sur une attaque ou les prémices d'une attaque, par exemple un balayage de ports, ils peuvent seulement nous informer qu'une incursion s'est produite. Ce qui serait rééllement utile est un système qui bloque effectivement ces attaques en temps réel. snort_inline est un système spécialement conçu à cet effet.

Cet article décrit comment compiler, installer et tester snort_inline. snort_inline est une adaptation du paquetage snort librement disponible, permettant l'examen et le rejet subséquent des paquets de réseau, pour autant qu'ils correspondent à certains critères prédéfinis. Ceci constitue un IPS (Intrusion Prevention System, système de prévention d'intrusion), au lieu d'une simple détection d'intrusion.

Ainsi, comment fonctionne réellement un IPS ? Le système charge une volumineuse table de signatures. Ces signatures prennent la forme d'une chaîne de données caractéristiques d'un certain type particulier d'attaque. Quand un paquet de données entre dans le réseau, l'IDS/IPS confronte ces éléments à sa base de données de signatures. Si les données concordent, alors l'IDS/IPS prend les mesures appropriées. S'il s'agit d'un IDS, la tentative d'intrusion sera enregistrée dans un journal, tandis que, dans le cas d'un IPS, le système peut supprimer le paquet de données, voire interrompre la connexion de la machine incriminée.

Au départ, si vous utilisez un système Red Hat/Fedora, il se peut que vous ayez besoin du code source du noyau installé dans votre système. Comme ce peut être vrai pour d'autres systèmes également, lisez la suite pour plus d'informations sur les conditions requises. Il est également utile d'avoir un serveur web en cours de fonctionnement, car cet article emploie le service web pour valider le comportement de snort_inline. Vous ne devriez pas l'essayer sur un serveur de production — du moins la première fois que vous essayez cette procédure.

Il faut quatre paquetages pour installer snort_inline afin de le configurer sur un système Fedora Core 3/4. Ceci peut être vrai pour d'autres systèmes également. Lisez la suite de cette section pour plus de détails. Nous partirons du principe que tous les fichiers sont teléchargés dans /home/snort/ : remplacez ce chemin par votre propre répertoire de téléchargement.

Pour commencer, il vous faut le code source d'iptables. À titre d'information, j'ai employé iptables-1.3.1 pour cet article. Une fois que vous avez l'archive tar (tarball) du source, déplacez-la dans /usr/src/, désarchivez-la, passez dans son répertoire à l'aide de la commande cd et exécutez make avec l'option install-devel :



mv /home/snort/iptables-1.3.1.tar.tar /usr/src/
cd /usr/src
tar xjvf iptables-1.3.1.tar.tar
cd /usr/src/iptables-1.3.1
make install-devel

Cela installera la bibliothèque libipq, permettant à snort_inline de communiquer avec iptables. iptables a pour mission d'accepter ou de rejeter les paquets sur l'interface réseau.

Ensuite, il est nécessaire de compiler et d'installer libnet, une API (Application Programming Interface, interface de programmation d'applications) haut niveau permettant à snort de construire et d'injecter des paquets dans le réseau. J'ai utilisé la version libnet-1.0.2a, comme spécifié dans la documentation snort_inline. La dernière version de libnet est pour l'instant incompatible avec snort. Une fois libnet-1.1.0.tar.gz téléchargé, suivez les instructions suivantes :



mv /home/snort/libnet-1.0.2a.tar.gz /usr/src/
cd /usr/src
tar xzvf libnet-1.0.2a.tar.gz
cd /usr/src/Libnet-1.0.2a
./configure
make
make install

Si aucune erreur ne s'est produite, vous pouvez passer à la section suivante. Si vous trouvez des erreurs à ce stade, il se peut que vous ayez à installer d'autres paquetages. Le troisième paquetage requis est pcre (Perl-Compatible Regular Expressions, la bibliothèque d'expressions régulières compatible avec Perl). À titre d'information, j'ai employé pcre-6.1.tar.gz. Une fois que vous avez téléchargé le fichier, suivez les étapes ci-dessous pour installer pcre :



mv /home/snort/pcre-6.1.tar.gz /usr/src/
cd /usr/src
tar xzvf pcre-6.1.tar.gz 
cd /usr/src/pcre-6.1
./configure
make
make install

Si aucune erreur ne s'est produite, vous pouvez passer à la section suivante.

Important

Les systèmes Red Hat/Fedora nécessitent une étape supplémentaire avant de pouvoir compiler snort_inline. Ceci n'a pas été testé sur d'autres systèmes, mais si votre compilation échoue ultérieurement avec le message d'erreur suivant ...



In file included from /usr/include/linux/netfilter_ipv4/ip_queue.h:10,
from /usr/include/libipq.h:37,
from ../../src/inline.h:8,
from ../../src/snort.h:38,
from spo_alert_fast.c:51:
/usr/include/linux/if.h:59: redefinition of `struct ifmap'
/usr/include/linux/if.h:77: redefinition of `struct ifreq'
/usr/include/linux/if.h:126: redefinition of `struct ifconf'
make[3]: *** [spo_alert_fast.o] Error 1
make[3]: Leaving directory
`/usr/src/snort_inline-2.3.0-RC1/src/output-peaving directory
`/usr/src/snort_inline-2.3.0-RC1/src/output-plugins'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/usr/src/snort_inline-2.3.0-RC1/src'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/usr/src/snort_inline-2.3.0-RC1'
make: *** [all] Error 2

...vous risquez de devoir effectuer les étapes correctives suivantes : la compilation échoue parce que les en-têtes de glibc doivent être mis à jour [1] et c'est la raison pour laquelle le source du noyau est requis, comme mentionné ci-dessus. Pour corriger temporairement ce problème, veuillez effectuer les ajustements suivants. Cette étape suppose que avez le source du noyau installé et qu'il se trouve dans linux-2.6.9. Ce répertoire est susceptible de changer, selon la version de votre noyau et de votre distribution.



cd /usr/include
mv linux linux.orig
ln -s /usr/src/redhat/SOURCES/linux-2.6.9/include/linux/ linux

Cette procédure peut toujours être inversée ultérieurement, si des problèmes surviennent. Vous devez obtenir maintenant le dernier paquetage de snort_inline. À titre d'information, j'ai employé snort_inline-2.3.0-RC1.tar.gz dans cet article. À présent, exécutez les commandes décrites ci-dessous.



mv /home/snort/snort_inline-2.3.0-RC1.tar.gz /usr/src/
cd /usr/src
tar xzvf snort_inline-2.3.0-RC1.tar.gz 
cd snort_inline-2.3.0-RC1
./configure
make
make install

S'il n'y a pas d'erreurs, alors félicitations ! Vous venez de compiler et d'installer avec succès snort_inline.


2. Configuration initiale

Nous devons apporter quelques réglages supplémentaires à la configuration de snort_inline, avant qu'il soit prêt à être lancer. Tout d'abord, il faut modifier le fichier de configuration de snort_inline, en le faisant pointer sur le chemin correct pour pouvoir obtenir ses règles. Ces règles indiquent à snort_inline quels sont les paquets malveillants et ceux qui font partie du trafic normal. Un contournement rapide consiste à déplacer les fichiers de règles de classification et de référence dans le répertoire des règles, comme suit :



cp /usr/src/snort_inline-2.3.0-RC1/etc/classification.config /usr/src/snort_inline-2.3.0-RC1/rules/
cp /usr/src/snort_inline-2.3.0-RC1/etc/reference.config /usr/src/snort_inline-2.3.0-RC1/rules/

Déplaçons les fichiers de configuration et de définition de règles dans le répertoire /etc, où résident habituellement les fichiers de ce type :



mkdir /etc/snort_inline
cp /usr/src/snort_inline-2.3.0-RC1/etc/* /etc/snort_inline/
cp /usr/src/snort_inline-2.3.0-RC1/rules /etc/snort_inline/ -R

Enregistrez le fichier et quittez. Par la suite, nous configurerons snort_inline pour qu'il s'exécute en tant que démon, c'est-à-dire comme processus d'arrière-plan, bien qu'il soit parfaitement imaginable que vous préfériez l'exécuter en tant que processus normal. Au départ, nous ne l'exécuterons en fait pas en tant que service d'arrière-plan non plus : le lancer en mode non démon nous permettra d'afficher la sortie de snort_inline et de nous assurer qu'il fonctionne comme prévu, sans erreur. Vérifions maintenant /etc/snort_inline/snort_inline.conf pour être sûrs que la spécification des chemins d'accès aux règles est comme requis ci-dessous. Chargez le fichier dans votre éditeur de texte favori et modifiez la ligne suivante :


var RULE_PATH /etc/snort_inline/drop_rules

en


var RULE_PATH /etc/snort_inline/rules 

Créons maintenant un répertoire pour snort_inline, pour enregistrer l'activité malveillante dans un journal :



mkdir /var/log/snort_inline

Par défaut, tout le trafic s'écoulant vers le noyau et refluant vers l'espace utilisateur doit être intercepté par snort_inline, pour vérifier la présence de paquets de réseau malveillants. Le noyau s'en charge en poussant les données dans une file d'attente à l'aide du module ip_queue. Vous pouvez charger ip_queue et vérifier sa présence comme suit :



modprobe ip_queue
lsmod | grep ip_queue

Si vous obtenez une ligne semblable à la ligne ci-dessous, ip_queue est actif et prêt à s'interfacer avec snort_inline :



ip_queue 9945 0

Ensuite, iptables doit être configuré pour envoyer le trafic à ip_queue. Cette redirection s'effectue à l'aide de la ligne suivante, qui redirige tous les paquets de réseau destinés au port 80 vers le module ip_queue. Si le serveur exécute un démon web, il est alors facile de vérifier qu'iptables fonctionne. Il n'est pas recommandé de faire ce test sur un serveur de production, car vos utilisateurs web subiront des coupures :



iptables -I INPUT -p tcp --dport 80 -j QUEUE

Si vous essayez maintenant d'explorer un site web hébergé sur le serveur depuis une autre machine, notez que votre navigateur se bloque. C'est parce que tous les paquets sont routés vers ip_queue et attendent d'être libérés par iptables. Une fois que snort_inline fonctionne en tache de fond, l'ensemble du trafic sera dirigé vers le serveur web, qui répondra à la demande de l'utilisateur de la façon habituelle.


3. Test de snort_inline

L'installation de snort_inline peut maintenant être testée à l'aide de la commande ci-dessous : snort_inline devrait commencer à traiter les paquets contenus dans la ip_queue et donc reprendre une activité réseau normale.



snort_inline -c /etc/snort_inline/snort_inline.conf -Q -N -l /var/log/snort_inline/ \
	-t /var/log/snort_inline/ -v

Vous devriez voir du texte défiler et snort_inline afficher un message semblable à celui-ci :



__== Initialisation Complete ==__

Dans l'affirmative, félicitations ! snort_inline fonctionne à présent. Essayez de vous connecter de nouveau via votre navigateur web. Vous devriez à présent voir la page web que vous attendiez. Si vous recevez un message similaire à celui ci-dessous, c'est que vous avez oublié de charger le module ip_queue :



Reading from iptables
Running in IDS mode
Initializing Inline mode 
InitInline: : Failed to send netlink message: Connection refused

De retour sur la machine ou s'exécute snort_inline, appuyez sur Ctrl+c pour mettre fin au processus snort_inline en cours. Il est temps maintenant d'ajouter une règle de test de façon à que vous puissiez voir si snort_inline fonctionne réellement. Dans cet exemple, nous allons rejeter toute l'activité sur le port 80. Pour ce faire, éditez /etc/snort_inline/rules/web-attacks.rules. Ouvrez-le à l'aide de votre éditeur favori et ajoutez la ligne suivante avant la première instruction alert, mais au-dessous des commentaires.



drop tcp any any -> any 80 (classtype:attempted-user; msg:"Port 80 connection initiated";)

Notez que toutes les autres lignes de ce fichier commencent par le mot alert. Cela signifie que snort_inline ne fera qu'enregistrer dans un journal et alerter en cas de paquets malveillants : il NE LES REJETTERA PAS. Ce point sera abordé dans un instant. Réexécutez snort_inline à nouveau avec la commande suivante :



snort_inline -c /etc/snort_inline/snort_inline.conf -Q -N -l /var/log/snort_inline/ \
	-t /var/log/snort_inline/ -v

Essayez une fois encore de créer une connexion à cette page web. Il se peut que vous deviez appuyer sur Ctrl+F5 pour forcer la page à se rafraîchir et empêcher votre navigateur d'afficher une version mise en cache. Votre requête devrait maintenant échouer. Vérifions maintenant rapidement les fichiers journaux, pour voir si snort_inline a capturé le « paquet malveillant ». De retour sur la machine ou s'exécute snort_inline, appuyez sur Ctrl+c une fois de plus pour arrêter le processus snort_inline et saisissez la commande suivante :



cat /var/log/snort_inline/snort_inline_full

Une séquence de sortie semblable à celle-ci devrait s'afficher :



[**] [1:0:0] Port 80 connection initiated [**]
[Classification: Attempted User Privilege Gain] [Priority: 1]
07/03-16:56:24.401627 192.168.16.68:2433 -> 192.168.16.7:80
TCP TTL:128 TOS:0x0 ID:24295 IpLen:20 DgmLen:48 DF
******S* Seq: 0x1EB0AE32 Ack: 0x0 Win: 0xFFFF TcpLen: 28
TCP Options (4) => MSS: 1460 NOP NOP SackOK
[**] [1:0:0] Port 80 connection initiated [**]
[Classification: Attempted User Privilege Gain] [Priority: 1]
07/03-16:56:27.341326 192.168.16.68:2433 -> 192.168.16.7:80
TCP TTL:128 TOS:0x0 ID:24297 IpLen:20 DgmLen:48 DF
******S* Seq: 0x1EB0AE32 Ack: 0x0 Win: 0xFFFF TcpLen: 28
TCP Options (4) => MSS: 1460 NOP NOP SackOK
[root@localhost 20050625]# 

Dans ce cas, félicitations, pour la troisième fois ! snort_inline a utilisé avec succès votre règle destinée à rejeter les paquets. La chaîne Port 80 connection initiated était la ligne que vous avez saisie dans web-attacks.rules plus haut. Nous pouvons également afficher une version plus courte, en émettant la commande suivante :



cat /var/log/snort_inline/snort_inline_fast

Celle-ci devrait afficher un message semblable à celui-ci :



07/03-16:56:24.401627 [**] [1:0:0] Port 80 connection initiated [**] [Classification:
Attempted User Privilege Gain] [Priority: 1] {TCP} 192.168.16.68:2433 -> 192.168.16.7:80
07/03-16:56:27.341326 [**] [1:0:0] Port 80 connection initiated [**] [Classification:
Attempted User Privilege Gain] [Priority: 1] {TCP} 192.168.16.68:2433 -> 192.168.16.7:80
[root@localhost 20050625]#

Pour pouvoir utiliser snort_inline efficacement, vous devez maintenant supprimer la règle de rejet ajoutée plus tôt. Éditez le fichier /etc/snort_inline/rules/web-attack.rules et ajoutez # au début de la ligne que vous avez ajoutée précédemment, ce qui fait que ;



drop tcp any any -> any 80 (classtype:attempted-user; msg:"Port 80 connection initiated";)

devient



#drop tcp any any -> any 80 (classtype:attempted-user; msg:"Port 80 connection initiated";)

La dernière étape consiste à modifier tous les fichiers de règles, en transformant les règles d'alerte en règle de rejet. Une commande simple peut suffire, mais il faut la saisir avec exactitude. Si vous n'êtes pas sûr, faites une sauvegarde de votre dossier de règles avant de saisir cette commande, chose que vous devriez faire régulièrement.



cd /etc/snort_inline/rules/
for file in $(ls -1 *.rules)
do
	sed -e 's:^alert:drop:g' ${file} > ${file}.new
	mv ${file}.new ${file} -f
done

Il ne reste plus qu'à exécuter snort_inline en tant que démon avec la ligne suivante, la seule différence étant la présence du -D :



snort_inline -c /etc/snort_inline/snort_inline.conf -Q -N -l /var/log/snort_inline/ \
	-t /var/log/snort_inline/ -v -D


4. Retour de votre système à la normale

Félicitations ! Vous venez d'installer un IPS opérationnel. Pour être exhaustif, les instructions suivantes montrent comment arrêter snort_inline et faire revenir votre système à son fonctionnement normal. Soyez averti que vous pouvez faire l'inverse en redémarrant simplement la machine.

Pour arrêter snort, dès lors qu'il fonctionne en mode démon, nous devons trouver le numéro d'identification de son processus, puis émettre un signal kill. Pour ce faire, exécutez la commande suivante ;



ps aux | grep snort_inline

ce qui devrait afficher une sortie similaire à celle-ci ; le nombre que nous cherchons est le « 15705 » :



root     15705  1.1 21.8  31184 27464 ?        Ss   22:37   0:01 snort_inline -c \
	/etc/snort_inline/snort_inline.conf -Q -N -l /var/log/snort_inline       \
	-t /var/log/snort_inline -v -D
root     15727  0.0  0.5   3760   720 pts/0    S+   22:39   0:00 grep snort_inline#

Maintenant, poursuivez et exécutez la commande kill, comme suit, où le nombre placé après kill est celui obtenu à l'étape précédente :



kill 15705

Cette commande sortira de snort, mais ip_queue recevra encore des paquets, perturbant le flux du trafic réseau. Comme indiqué précédemment, dans cet exemple, tout le trafic du port 80 sera désactivé. Pour rétablir ce trafic, nous devons supprimer la règle iptables avec la commande suivante :



iptables -D INPUT -p tcp --dport 80 -j QUEUE

Votre serveur devrait maintenant reprendre son activité réseau normale sur le port 80.


5. Programme des réjouissances

Cet article est une introduction au monde de snort_inline. Le sujet du mois prochain sera consacré à la mise à jour des règles de snort_inline, à l'écriture de vos propres règles personnalisée et à la création d'un script de démarrage pour snort_inline permettant de l'activer au démarrage.

Pete programme depuis l'âge de 10 ans sur un vieil Atari 800 XE©. Bien qu'il ait obtenu le diplôme d'ingénieur acoustique à la ISVR mondialement connue, à Southampton (Royaume-Uni), l'appel de la programmation lui a fait rebrousser chemin et depuis, il travaille comme développeur web. Il utilise à la fois les plates-formes Linux et Windows. Il vit toujours au Royaume-Uni, où il coule actuellement des jours heureux avec son épouse.

Notes

[1]

Commentaires de Rick Moen : soyez prudent quand vous bidouillez les en-têtes d'un noyau. L'ancienne méthode pour le faire en récupérant un nouveau source de noyau et en le désarchivant dans /usr/src/linux était toujours problématique. Elle est à présent rendue obsolète par des méthodes meilleures et moins brutales.

Explication sommaire : les fichiers d'en-têtes du noyau utilisés lors de la compilation doivent toujours être compatibles avec le paquetage libc installé. Par conséquent, vous ne devriez jamais les bidouiller, à moins d'installer un nouveau paquetage libc qui fournit de nouveaux en-têtes compatibles.

Explication détaillée : pendant la compilation, certains fichiers d'en-tête du noyau sont invoqués depuis des emplacements au sein du répertoire /usr/include/linux. Au début de l'histoire de Linux, quelqu'un a mis en application la notion, qui semblait bonne à l'époque, de ne pas placer de tels en-têtes dans /usr/include/linux, mais plutôt — pour préserver de l'espace sur le disque, peut-être ? — de créer un lien symbolique d'ici vers l'emplacement de ces mêmes fichiers d'en-tête dans l'arborescence du code source du noyau désarchivé dans /usr/src/linux. Malheureusement, pendant que vous mainteniez votre système au fil du temps, de nouvelles arborescences de fichiers d'en-têtes du noyau ont accumulé inévitablement de subtiles incompatibilités avec les points d'entrées des bibliothèques C installées. Finalement, les compilations commencent à échouer pour de mystérieuses raisons.

La cause de ce syndrome a été comprise rapidement, mais l'habitude de lier symboliquement des en-têtes vers /usr/src/linux est devenue si enracinée qu'il a fallu attendre jusqu'à 1999 pour l'éradiquer des distributions Linux, en dépit des incitations répétées de Torvalds et de l'analyse approfondie de l'Answer Gang®.

Ce que l'auteur appelle « mettre à jour les en-têtes de glibc » apparaît à ce commentateur comme un exemple de la « folie des liens symboliques » que Torvalds et d'autres tentent d'éradiquer depuis 8 ans. Personnellement, je ne partage pas cet avis. Si « la compilation échoue » à cause de problèmes d'en-têtes, je parie que vous avez induit ces problèmes vous-même en raison de vos bidouillages avec le contenu de /usr/include/linux. Le remède réel consiste à cesser cette pratique et à laisser les fichiers système d'en-tête tels que votre paquetage glibc les a déclarés.