Présentation de l'IDS/IPS Suricata

MISC n° 066 | mars 2013 | Eric Leblond
Creative Commons
  • Actuellement 0 sur 5 étoiles
0
Merci d'avoir participé !
Vous avez déjà noté cette page, vous ne pouvez la noter qu'une fois !
Votre note a été changée, merci de votre participation !
L'IDS/IPS Suricata est une sonde de détection/prévention d'intrusion développée depuis 2008 par la fondation OISF. IDS à base de signatures, il offre des possibilités intéressantes en termes d'analyse protocolaire et de suivi de l'activité réseau.

1. Un IDS/IPS à base de signature

Suricata [SURICATA] est un IDS/IPS basé sur des signatures qui est distribué sous licence GPL v2. Il s'agit d'un développement parti de zéro qui a été initié en 2008 par Victor Julien. Il reste depuis lors le leader du projet mais Suricata est juridiquement un projet de l'Open Information Security Foundation [OISF]. Cette fondation de droit américain et à but non lucratif a été créée pour recevoir les fonds nécessaires au développement de Suricata. En effet, conscient de l'ampleur de la tâche, près de 300 000 lignes de code à ce jour, Victor Julien et Matthew Jonkman (fondateur d'Emerging Threats [ET]) ont décidé dès les prémisses du projet de chercher des fonds pour constituer une équipe de développeurs à même de mener à bien le projet. Les fonds ont tout d'abord été ceux du projet HOST (pour Homeland Open Security Technology) et leur répartition est passée progressivement (conformément à la volonté initiale du Homeland) d'une prédominance des fonds étatiques à une prédominance des fonds provenant des industriels membres du consortium. Le projet bénéficie d'une étonnante décorrélation entre financement et développement. La feuille de route est en effet définie lors de réunions ouvertes au public sans qu'il y ait d'intervention des bailleurs de fonds. C'est donc un projet communautaire et opensource, disponible et ouvert tant aux idées qu'aux contributions.

La première version stable de Suricata date de 2010. L'objectif de cette version était d'avoir un moteur d'IDS/IPS multithread supportant le langage de signatures de Snort [SNORT], ce qui permettait de conserver l'existant en termes de signatures. Des fonctions avancées étaient déjà présentes dans cette version avec notamment le support de la détection automatique des protocoles et des mots-clés utilisables pour accéder aux champs normalisés des protocoles comme HTTP. L'ajout des mots-clés protocolaires au langage de règles standards est ainsi une des fonctions différenciantes de Suricata qui est apparue dès la première version stable. Depuis 2010, le développement se focalise sur l'amélioration des performances et sur l'ajout de nouveaux protocoles. Le dernier en date est TLS avec un décodeur de négociations éponyme qui fournit au moteur de détection les informations sur les certificats échangés par les sessions. Il est ainsi possible de vérifier si les sessions TLS sont correctes (certificats signés par une autorité connue par exemple).

Suricata a différents modes de fonctionnement. S'il peut être configuré en tant que dispositif de prévention d'intrusion en s'appuyant sur Netfilter ou ipfw (sous FreeBSD), il supporte aussi de nombreux modes de capture en mode IDS qui vont de pcap, le standard de facto, au support des cartes d'acquisitions.

1.1 Un moteur de détection

Suricata est un moteur de détection et ne réalise donc que la capture, la détection et la création d'alertes ou de fichiers de journalisation. Tant la partie modification régulière du jeu de signatures que les interfaces de consultation des alertes sortent de son champ d'action. Une solution complète doit donc s'appuyer sur d'autres logiciels. Si l'on devait considérer un système type, il s'agirait vraisemblablement d'un système comme celui présenté sur la figure suivante :

Il utilise barnyard2 pour transférer les alertes du format binaire unified2 vers une base de données. L'interface utilisateur est une application de consultation des alertes comme snorby [SNORBY] ou un système de gestion des événements de sécurité encore appelé SIEM [SIEM].

L'une des tâches les plus importantes de Suricata est la reconstruction du trafic. Chacune des couches du modèle OSI doit être reconstruite correctement et cela induit la gestion de la fragmentation IP, de la segmentation TCP ainsi que de l'ensemble des types d'invalidités (incohérence dans les longueurs annoncées, somme de contrôle non correcte, taille de fenêtre TCP invalide). Suricata réalise aussi pour certains protocoles une décomposition et une normalisation. Le schéma suivant résume ce travail sur un flux HTTP d'exemple :

Après la validation de la couche IP et la défragmentation, la reconstruction est effectuée au niveau TCP et le flux de données est ensuite reconstitué (streaming). Lorsqu'un support applicatif existe dans Suricata, ceci conduit à une normalisation du flux applicatif.

Des mots-clés adaptés offrent une granularité complète pour l'écriture de signatures. Celles-ci peuvent porter sur les différentes couches présentées dans le schéma.

Pour faire une recherche de motif sur chaque paquet, il faut utiliser le mot-clé tcp-pkt :

alert tcp-pkt any any -> any 80 (msg:"HTTP dl";

 content:"Get /download.php"; sid:1; rev:1;)

Ce type de règle n'émettra aucune alerte si le contenu est réparti sur plusieurs paquets. Pour pallier ce problème, il est possible d'émettre une alerte au niveau du flux reconstruit en utilisant la règle suivante :

alert tcp any any -> any any (msg:"HTTP download";

flow:established,to_server;

 content:"Get /download.php";)

On notera la sensibilité à la casse sur le mot « Get » et la non-résistance à toute modification valide au niveau HTTP de la chaîne, comme l'ajout d'un deuxième espace avant le début de l'URI.

Une alerte sur le flux HTTP normalisé est obtenue en utilisant la règle suivante :

alert http any any -> any any (msg:"HTTP download";

 content:"GET"; http_method;

 content:"/download.php"; http_uri;)

Cette dernière règle montre l'intérêt de la normalisation dans la fiabilisation des signatures. En recherchant les correspondances sur un trafic reconstruit et normalisé, l'ensemble des techniques d'évasions classiques sont contrées. Celles-ci reposent principalement sur l'utilisation de transformations sur le trafic visant à fausser la vision qu'a l'IDS du trafic réellement reçu par la ressource surveillée. Les attaques peuvent consister à découper les paquets, à jouer sur la segmentation, à obfusquer les requêtes applicatives. Comme l'IDS reconstruit et normalise le trafic, l'impact de ces transformations est donc théoriquement nul. Théoriquement, car les algorithmes de gestion de la fragmentation et de la segmentation diffèrent suivant les systèmes d'exploitations. Si le traitement de l'IDS est unifié, il est possible de cacher une attaque en jouant sur ces différences d'interprétation des RFC. De ce fait, Suricata intègre une gestion de la personnalité et réalise pour chaque IP à protéger une reconstruction correspondant au système d'exploitation qui a été lié à cette adresse IP. Les protocoles applicatifs souffrent souvent du même problème et c'est particulièrement le cas pour HTTP. Aussi est-il possible de configurer la personnalité des serveurs web.

Pour ce qui est des événements protocolaires (comme la somme de contrôle invalide par exemple), des mots-clés et des fichiers de signatures fournis dans Suricata leur sont dédiés. Dans le cas du schéma précédent, les signatures intéressantes sont les suivantes :

alert ip any any -> any any (msg:"SURICATA IPv4 invalid checksum"; ipv4-csum:invalid; sid:2200073; rev:1;)

alert tcp any any -> any any (msg:"SURICATA STREAM ESTABLISHED packet out of window"; stream-event:est_packet_out_of_window; sid:2210020; rev:1;)

La première signature va déclencher une alerte sur le paquet numéro 4 du schéma grâce au mot-clé ipv4-csum. La deuxième règle va alerter sur le datagramme 6,7 par le jeu du mot-clé stream-event suivi de l'option est_packet_out_of_window.

1.2 Une configuration exhaustive

La configuration de Suricata se fait au moyen d'un fichier au format YAML (YAML Ain't Markup Language) qui contient l'ensemble des directives de configuration. Certaines variables sont aussi positionnables depuis la ligne de commandes. Dans ce cas, la ligne de commandes prévaut sur le fichier de configuration. La syntaxe du YAML [YAML] est structurée mais reste lisible pour un être humain. L'extrait suivant montre comment, dans le mode de capture AF_PACKET, les paramètres des interfaces eth0 et eth1 peuvent être configurés :

af-packet:

  - interface: eth0

    threads: 1 # un seul thread de capture

    cluster-id: 99

  - interface: eth1

    threads: 2 # deux threads sont utilisés pour la capture des paquets sur eth1

    cluster-id: 98 # les deux threads sont liés au même groupe 98

La configuration contient aussi la liste des fichiers de signatures à utiliser :

default-rule-path: /home/eric/builds/suricata/etc/suricata/rules

rule-files:

- botcc.rules

- ciarmy.rules

Un des autres points importants lors de la configuration de Suricata est le positionnement des variables définissant l'utilisation de la mémoire. Pour de nombreuses fonctions, il est possible de spécifier l'utilisation mémoire et la taille maximale des structures. Par exemple, la table des flux est configurée de la manière suivante :

flow:

  memcap: 32mb

  hash-size: 65536

  prealloc: 10000

  emergency-recovery: 30

La variable memcap détermine quelle est la quantité maximale de mémoire à utiliser pour la gestion des flux. Le paramètre prealloc spécifie quant à lui le nombre d'éléments à pré-allouer au démarrage du logiciel. Ceci diminue le coût des allocations en cours de fonctionnement aux dépens de l'utilisation mémoire initiale du logiciel. Enfin, la variable emergency-recover est un des paramètres de la gestion des situations de stress. Lorsque le nombre de flux atteint la limite mémoire, Suricata rentre en mode urgence et nettoie les entrées de la table des flux de manière plus agressive. Il utilise pour cela des délais d'expiration plus courts (paramétrés dans le fichier de configuration). Le paramètre emergency-recover spécifie à partir de quel pourcentage de flux libres le mode normal reprend effet.

Le lancement de Suricata s'effectue alors depuis le script d'init ou depuis la ligne de commandes :

suricata -c /etc/suricata/suricata.yaml --af-packet=eth0

ou encore si l'on veut utiliser le fichier de configuration par défaut et toutes les interfaces décrites dans la section af-packet :

suricata --af-packet

La seule option nécessaire est en effet le mode de capture.

1.3 Haute performance avec Suricata

Comme tous les IDS, Suricata a été développé avec deux objectifs qui sont sécurité et performance. Du côté de la sécurité, des bonnes pratiques de développement sont en place : les fonctions dangereuses sont interdites, la programmation défensive est la règle, plusieurs milliers de tests unitaires ont été implémentés. Des audits fréquents sont réalisés avec des outils d'analyse statique comme cppcheck ou encore coverity (dans le cadre du projet Coverity Scan Initiative).

Au niveau des performances, le choix de conception le plus fort a sans aucun doute été de faire le pari du multithreading. Pari puisque l'avis de certaines personnes éminentes comme Marty Roesh, auteur de snort et CTO de Sourcefire, était que le multithreading ne pouvait pas s'appliquer aux IDS [SNORT3].

Compte tenu de la diversité tant au niveau des situations matérielles que des modes de captures, la gestion et l'agencement des différentes tâches devaient pouvoir être paramétrés de manière variable. Toute une série de modes de fonctionnement est donc disponible. Ces modes proposent des organisations variées qui s'avèrent plus ou moins adaptées suivant les environnements. On trouve ainsi des modes comme workers effectuant pour un paquet donné tout les tâches sur un seul thread et des modèles plus complexes comme autofp qui sépare les différentes tâches, comme le montre le schéma suivant :

Les différentes tâches propres à un IDS (capture, défragmentation, streaming, détection, sortie) peuvent ainsi être réparties sur des cœurs multiples et le nombre de threads ainsi que leur affinité peuvent être définis dans la configuration.

Si l'organisation des threads est un des facteurs de performance, Suricata s'appuie aussi sur un support étendu des cartes de captures (les cartes Myricom, Napatech ou encore PF_RING DNA sont supportées) et sur un moteur de signatures performant. Ce dernier construit notamment une vision globale du jeu de règles afin d'éviter une évaluation linéaire des signatures pour chaque paquet. Les techniques employées sont le multi pattern matching utilisant Aho Corasick [AC] ou d'autres algorithmes du même type et une classification des règles découpant le jeu de règles en plusieurs blocs.

Du côté des chiffres, la version 1.3.1 a été déployée par l'équipe de l'OISF en mode IDS sur un serveur doté d'un seul CPU Xeon à 2.7GHz et de 32Go de mémoire et équipé d'une carte Intel gérant le multiqueue (répartition de la réception des paquets sur plusieurs interruptions système). Avec un jeu de près de 7000 règles, Suricata réussit à analyser en continu un trafic réel de 9.5 gpbs pour 1,5M paquets par seconde (voir [10GBPS] pour plus d'informations). Le choix a été fait de n'utiliser que du code d'origine sur la distribution utilisée et c'est donc la capture AF_PACKET qui a été choisie. Les noyaux Linux récents bénéficient d'un mécanisme de capture multi socket (répartition de charge à la capture) et cette fonctionnalité est à la base de l'organisation qui a été utilisée comme le montre le schéma suivant :

Son principe est d'effectuer le traitement de chaque flux sur un seul CPU. La répartition par flux est réalisée par la carte réseau qui effectue la répartition de charge et le traitement est ensuite effectué par les threads de Suricata qui sont alignés sur le CPU de capture de manière à bénéficier tant du cache processeur que du positionnement de l'interruption de capture sur ce CPU.

2. Fonctions différenciantes

2.1 Découverte des protocoles

Suricata intègre un moteur d'identification des protocoles qui analyse les flux à la recherche de motifs pour découvrir le protocole utilisé. Ce mécanisme a un intérêt double. Tout d'abord, il permet de détecter des communications effectuées sur des ports non standards. Ceci est particulièrement utile lors de la détection des canaux de contrôles des malwares. Le protocole HTTP est en effet très souvent utilisé et nombre de malwares utilisent des ports non standards pour échapper à la détection. Avec la détection automatique, Suricata est capable d'appliquer les règles d'analyse quel que soit le port et ceci augmente considérablement le niveau de détection. Enfin, la découverte de protocoles réduit le risque de faux positifs. Supposons en effet qu'une signature recherche un motif court dans un flux qui est censé être du HTTP :

alert tcp $HOME_NET any -> $EXTERNAL_NET $HTTP_PORTS (content:"34af")

Sans identification protocolaire, ce motif va être recherché sur tous les flux à destination des ports HTTP (80, 8080, …) et cela même si un flux chiffré transite sur un de ces ports. Dans le cas de Suricata, l'utilisation du mot-clé http limite la recherche aux flux HTTP, aucun flux chiffré ne sera analysé :

alert http $HOME_NET any -> $EXTERNAL_NET any (content:"34af")

Il y a donc moins de trafic analysé, donc de meilleures performances et la précision de détection est même augmentée.

La faiblesse de ce mécanisme est la sensibilité de l'algorithme de détection aux méthodes d'évasions. Si l'attaquant parvient à contourner la reconnaissance, il passe alors inaperçu pour toutes les règles de ce protocole. Certaines de ces attaques reposent sur les propriétés de retransmission de TCP et l'envoi de paquets leurres [HACKLU]. Elles sont heureusement bien souvent détectables au vu des anomalies protocolaires qu'elles entraînent.

2.2 Analyse protocolaire et mots-clés dédiés

Comme nous l'avons vu précédemment, l'analyse protocolaire simplifie et sécurise l'écriture de règles. Les champs accédés sont normalisés et donc la règle n'a pas à prendre en compte les techniques d'évasions communes ou même liées au protocole (HTTP chunk par exemple). De plus, la recherche de motif est plus précise puisque Suricata cherche seulement les chaînes dans la partie indiquée du protocole.

La règle suivante, dont le but est de générer une alerte lorsque le chat intégré à Facebook est utilisé, montre comment, dans le cas du protocole HTTP, ces différents mots-clés protocolaires peuvent être utilisés :

alert http $HOME_NET any -> $EXTERNAL_NET any \

(

msg:"ET CHAT Facebook Chat (send message)"; \

flow:established,to_server; content:"POST"; http_method; \

content:"/ajax/chat/send.php"; http_uri; content:"facebook.com"; http_header; \

classtype:policy-violation; reference:url,doc.emergingthreats.net/2010784; \

reference:url,www.emergingthreats.net/cgi-bin/cvsweb.cgi/sigs/POLICY/POLICY_Facebook_Chat; \

sid:2010784; rev:4; \

)

Juste après alert, le mot-clé http indique que la règle porte sur les flux dont le protocole détecté est HTTP. Ces flux doivent aller de $HOME_NET, qui est une variable de configuration qui s'évalue en une liste de réseaux, vers $EXTERNAL_NET. Les ports source et destination sont laissés libres car any est utilisé.

La partie « content:"POST"; http_method; » signifie que le trafic recherché utilise POST comme méthode HTTP. De la même manière, la partie suivante de la règle « content:"/ajax/chat/send.php"; http_uri; » spécifie que l'URL doit correspondre à l'expression derrière content. Enfin, « content:"facebook.com"; http_header » indique que le header HTTP doit contenir facebook.com.

Le décodage du protocole HTTP est mis à profit de deux manières. D'une part par l'existence de mots-clés dédiés comme http_uri, http_user_agent ou encore http_method, mais aussi d'autre part par la journalisation des requêtes HTTP effectuées dans un format semblable à celui d'un journal Apache. Ce qui offre une visibilité intéressante sur une partie de l'activité du réseau.

Ce type de mots-clés est disponible pour les protocoles SSH, HTTP et TLS.

2.3 Interaction avec les transferts de fichier

La compréhension par Suricata du protocole HTTP a tout naturellement conduit à la volonté d'extraire et d'analyser les objets transitant sur ce protocole. C'est possible depuis la version 1.3 avec l'ajout d'une série de mots clés dédiés à l'étude et à l'analyse des fichiers envoyés ou reçus sur le protocole HTTP.

Il y a tout d'abord une série de mots-clés visant à identifier les fichiers. Pour partir d'un exemple, voici une signature générant une alerte lorsqu'un fichier a une extension jpg mais n'est pas un fichier JPEG :

alert http any any -> any any (msg:"canada dry"; fileext:"jpg"; filemagic:!"JPEG image data")

Le mot-clé fileext valide que l'extension du fichier est jpg et le mot-clé filemagic utilise la bibliothèque magic qui est la base de la commande Unix file pour déterminer quel est le type du fichier.

Une alerte est certes intéressante mais son intérêt est limité s'il n'est pas possible d'analyser le fichier coupable. Pour déclencher le stockage d'un fichier si une signature est activée, il suffit d'ajouter le mot-clé filestore. Le fichier est alors sauvegardé sur disque et est accompagné d'un fichier contenant les informations relatives aux conditions de la capture. Il faut réellement s'inquiéter s'il est possible dans votre environnement de reconstituer une PKI à l'aide de la règle suivante :

alert http $HOME_NET any → $EXTERNAL_NET any (msg:”outgoing private key”; filemagic:”RSA private key”; filestore)

Une autre fonction intéressante de ce sous-système est la gestion des MD5 des fichiers, le mot-clé filemd5 prend en paramètre un fichier qui contient une liste de sommes de hachage MD5. Il est ainsi possible de détecter tout transfert ou téléchargement d'un fichier non autorisé. Par exemple, la règle suivante émettra une alerte lors du téléchargement de fichiers exécutables ne figurant pas dans la liste blanche et stockera le fichier téléchargé :

alert http $EXT_NET any → $HOME any (msg:”non connu”;

 filemagic:”PE32 executable”;

 filemd5:!whitelist.txt ; filestore)

Ce mécanisme peut être enrichi en utilisant la journalisation des transferts de fichiers. Couplé avec le script de surveillance disponible dans le répertoire contrib de Suricata, il est possible d'effectuer en continu des vérifications de dangerosité des fichiers sur des sites comme anubis.iseclab.org, malwr.com, threatexpert.com ou encore Virustotal en utilisant le md5 des fichiers.

Le support de l'extraction de fichier est actuellement en cours d'extension pour le protocole SMTP. Une implémentation existe mais elle n'est pas encore intégrée aux sources officielles.

2.4 Parseur de négociation TLS

En 2011, Pierre Chifflier de l'ANSSI a développé un parseur de négociation SSL/TLS qui a été intégré à Suricata. Suite aux failles en série des autorités de certifications lors de cette année 2011, la capacité à comprendre et à étudier les négociations SSL/TLS pour en extraire les paramètres est apparue comme un moyen efficace d'améliorer la sécurité grâce à Suricata. Ce parseur a donné naissance à une série de mots-clés et de fonctionnalités. L'analyse de la négociation expose en effet les paramètres clés qui sont utilisables pour écrire des règles précises. Par exemple, tls.subject est une vérification sur le sujet du certificat serveur et tls.issuerdn est une vérification sur le nom distingué du signataire du certificat. La règle suivante utilise ces deux mots-clés pour émettre une alerte lorsqu'un certificat google apparaît comme étant forgé (car il n'est pas signé par la bonne autorité) :

alert tls any any -> any any (msg:"forged ssl google user";

 tls.subject:"CN=*.googleusercontent.com";

 tls.issuerdn:!"CN=Google-Internet-Authority";

 sid:8; rev:1;)

Un autre mot-clé est tls.fingerprint qui vérifie cette fois-ci l'empreinte SHA1 d'un certificat contre la valeur de l'option. Il est ainsi possible de détecter des changements de certificats sur des entités maîtrisées :

alert tls any any -> any any (msg:"Regit fingerprint";

         tls.subject:"CN=home.regit.org";

         tls.fingerprint:!"f3:40:21:48:70:2c:31:bc:b5:aa:22:ad:63:d6:bc:2e:b3:46:e2:5a"; sid:114;

         tls.store;)

Cette dernière signature utilise aussi la fonctionnalité de stockage des certificats. Si une alerte est émise, il y a aussi écriture sur le disque de la chaîne des certificats du serveur, le tout accompagné d'un fichier de description contenant les éléments relatifs à l'événement qui a causé la génération de ce fichier.

Enfin, la dernière fonctionnalité notable de l'analyse TLS est la possibilité de générer un fichier journal contenant les paramètres de chaque connexion TLS. Ce fichier constitue une source de données intéressante pour effectuer des analyses statistiques sur les flux TLS/SSL.

2.5 Nouveautés de la version 1.4

2.5.1 Liste des nouveautés

La version 1.4 a été l'occasion d'un travail sur les performances avec de nombreuses améliorations. Mais c'est surtout la précision du moteur qui a été améliorée. C'est notamment le cas du support d'IPv6, des rapports de bogues venus de France ont permis son amélioration notamment grâce au traitement de certains cas spécifiques et l'ajout du décodage d'un certain nombre de protocoles : IPv4 in IPv6, Ipv6 in IPv6 et Teredo (protocole d'encapsulation de IPv6 dans IPv4 de Microsoft). Le langage de signature a aussi évolué afin de pouvoir réaliser des signatures matchant exclusivement sur IPv4 ou IPv6.

Le support de TLS a vu l'ajout du mot-clé tls.storage qui déclenche le stockage de la chaîne de certificats serveurs sur disque lorsqu'une signature comportant ce mot-clé matche.

La version 1.4 voit aussi l'apparition d'un nouveau mode de fonctionnement. Appelé AF_PACKET IPS, il s'agit d'une évolution de la capture AF_PACKET. En utilisant deux interfaces Ethernet dédiées, Suricata constitue un pont transparent de niveau 2. Toute trame arrivant sur une interface est réémise sur l'autre interface. Ce mode de fonctionnement sera décrit plus en détail dans un prochain article.

Mais les deux nouveautés les plus intéressantes sont sans doute l'ajout du scripting lua aux règles et l'interaction avec Suricata par le biais d'une socket Unix.

2.5.2 Unix socket

Le principe de cette fonctionnalité est extrêmement classique. Suricata écoute sur une socket Unix et il est possible pour un client de s'y connecter et de passer des commandes à Suricata par ce biais. La communication entre Suricata et le client se fait au moyen d'un protocole défini au-dessus de JSON. Ce format a été choisi afin de rendre possible l'échange d'éléments complexes et le développement de clients dans de nombreux langages grâce aux bibliothèques JSON existantes.

En mode de fonctionnement normal, la liste des commandes disponibles dans la version 1.4 n'est pas réellement impressionnante puisqu'il est simplement possible d'arrêter Suricata et de récupérer des statistiques sur les interfaces monitorées.

L'intérêt principal de ce moyen de communication réside en effet dans le mode de fonctionnement unix-socket. De nombreuses entités reçoivent un nombre important de fichiers pcap (sortie d'équipement, pot de miel) et procèdent à une analyse de ces fichiers. En fonctionnement normal, il faut lancer une instance de Suricata pour chaque fichier et donc consacrer plusieurs dizaines de secondes à la construction du jeu de signatures. Si le nombre de fichiers Pcap est important, cela entraîne un délai voire l'accumulation de retard dans le traitement. Le mode unix-socket règle ce problème puisqu'il est possible de demander le traitement d'un fichier en envoyant un message sur la socket. Le traitement des fichiers est alors fait sans recalcul de l'arbre des signatures et le gain de temps est donc considérable.

L'utilisation de ce mode est simple, il suffit de lancer Suricata avec l'option unix-socket :

suricata --unix-socket

Le script d'exemple suricatasc peut alors être utilisé pour ajouter des fichiers :

# suricatasc

>>> pcap-file /home/eric/pcap/file10.pcap /home/eric/pcap/dir10

Success: Successfully added file to list

>>> pcap-file-list

Success: {'count': 2, 'files': ['file9.pcap', 'file10.pcap']}

Il y a ici deux commandes, la première demande le traitement du fichier file10.pcapen utilisant le répertoire dir10 comme sortie. La deuxième commande liste les fichiers en attente de traitement.

Le format des commandes est simple de manière à ce que le développement d'un client le soit aussi. Par exemple, l'ajout d'un fichier se fait au moyen de la commande :

{

   "command": "pcap-file",

   "arguments": { "filename": "smtp-clean.pcap", "output-dir": "/tmp/out" }

}

Et le retour par le serveur est de la forme :

{

   "return": "OK|NOK",

   "message": JSON_OBJECT or information string

}

Ce mécanisme d'échanges avec Suricata sera sans doute de plus en plus utilisé et sera vraisemblablement le moyen pour interagir avec les composantes dynamiques de la détection, comme les personnalités des hôtes ou des serveurs ou encore le système de réputation IP.

2.5.3 Script Luajit

L'un des premiers choix ayant été fait lors du développement de Suricata a été de réutiliser le langage de signature développé pour Snort. Assurer une compatibilité permettait de réutiliser les jeux de règles existants, mais surtout n'imposait pas de nouveaux apprentissages aux experts du domaine. Comme nous l'avons vu, la syntaxe a évolué et des mots-clés ont fait leur apparition. Des fonctionnalités comme flowbits ou flowvar [FLOWKWD] peuvent être utilisées pour écrire des signatures complexes, mais le niveau de mise en œuvre est élevé si on considère le résultat obtenu. Aussi, la version 1.4 a vu l'apparition de Luajit [SURILUA] qui est utilisable dans une règle pour évaluer un script Lua et utiliser son retour comme un test. Ceci apporte plus de flexibilité et de puissance dans l'écriture des tests.

Une règle évaluera un script si le mot-clé luajit est utilisé :

alert http any any -> any any (msg:"LUAJIT HTTP test"; luajit:test.lua; sid:1;)

Le script Lua doit contenir deux fonctions. Il commence par une fonction d'initialisation init où l'utilisateur spécifie quels sont les champs auxquels il souhaite accéder dans la partie active du script :

function init (args)

    local needs = {}

    needs["http.request_line"] = tostring(true)

    return needs

end

Le corps du script est une fonction appelée match qui retourne 1 si la condition recherchée est vérifiée et 0 si ce n'est pas le cas :

function match(args)

    a = tostring(args["http.request_line"])

    if #a > 0 then

        if a:find("^POST%s+/.*%.php%s+HTTP/1.0$") then

            return 1

        end

    end

    return 0

end

Les éléments exportés sont accessibles depuis le tableau args.

L'intérêt de Lua est d'une part de pouvoir utiliser des éléments de logiques complexes dans les tests, mais aussi de pouvoir utiliser des fonctions non accessibles dans le langage de règles. Il est ainsi possible, comme l'a fait Guillaume Prigent [LUAEVIL], de réaliser une implémentation de la RFC 3514 [RFC3514] aussi connue sous le nom de RFC evil flag. Le principe de cette RFC publiée le 1er avril 2003 consiste à utiliser le bit de sécurité de IPv4 pour détecter les paquets malicieux. Dans le cas d'un IDS, la tâche est plus complexe puisqu'il est nécessaire de prendre en compte les faux positifs. Le script Lua peut donc être décomposé en deux phases, tout d'abord utilisation de la fonction Lua math.random pour la génération des faux positifs, puis accès au bit de sécurité dans le paquet :

function match(args)

    local random = math.random(0,100)

    if random <= 10 then

        return 1 -- To be RFC3514 compliant (false positives)

    end

    local ip_offset = 14 -- Assuming it's ETHER packet

    local b1,b2

    b1, b2 = string.byte(v, ip_offset+6+1), string.byte(v, ip_offset+6+2)

    local ip_header_frag_buff = b1*256 + b2

    local evil_flag = bit.band(ip_header_frag_buff, 0x8000)~=0

    if evil_flag == true and math.random(0,100) > 8 then -- False negative

        return 1

    end

    return 0

end

Les performances de Luajit semblent tenir la comparaison par rapport à des règles utilisant des expressions régulières et compte tenu des avantages en termes de souplesse, il est probable que ce système sera un des points forts de Suricata dans les années à venir.

Conclusion

Suricata est donc un IDS à base de signatures qui offre, par sa compréhension des protocoles et ses fonctionnalités d'extractions, des possibilités intéressantes. De plus, ses performances et sa facilité de passage à l'échelle autorisent son déploiement dans la plupart des environnements.

Le développement de Suricata est très actif et de nombreuses fonctionnalités apparaissent pour chaque version. Elles sont le plus souvent expliquées dès leur introduction dans les sources sur les blogs des développeurs. Ceux-ci sont accessibles depuis le planète Suricata [PLANET].

Si vous souhaitez tester Suricata, sachez qu'il est disponible dans la plupart des distributions. Cependant, une distribution comme Security Onion [SECUONION] est sans doute l'une des méthodes les plus simples car vous obtiendrez après avoir répondu à quelques questions un Suricata et un ensemble d'interfaces prêtes à l'emploi.

Références

[SURICATA] Suricata : http://suricata-ids.org/

[OISF] Open Information Security Foundation : http://www.openinfosecfoundation.org/

[ET] Emerging Threats : http://www.emergingthreats.net/

[SNORT] Snort : http://www.snort.org

[10GBPS] Suricata, to 10Gbps and beyond : https://home.regit.org/2012/07/suricata-to-10gbps-and-beyond/

[SNORBY] Snorby : https://snorby.org/

[SIEM] Page Wikipedia dédiée au SIEM : http://en.wikipedia.org/wiki/Security_information_and_event_management

[SNORT3] Single thread data processing : http://vrt-blog.snort.org/2010/06/single-threaded-data-processing.html

[AC] Aho Corasick sur Wikipedia : http://fr.wikipedia.org/wiki/Algorithme_d%27Aho-Corasick

[HACKLU] The menace came from below : http://archive.hack.lu/2012/menace-came-from-below.pdf

[YAML] Spécification de YAML : http://www.yaml.org/spec/1.2/spec.html

[FLOWKWD] Documentation des variables de flux https://redmine.openinfosecfoundation.org/projects/suricata/wiki/Flow-keywords

[SURILUA] : Documentation du support Luajit de Suricata https://redmine.openinfosecfoundation.org/projects/suricata/wiki/Lua_scripting

[LUAEVIL] : A Lua implementation of RFC 3514 for suricata https://github.com/regit/luaevilbit

[RFC3514] : RFC 3154 http://www.ietf.org/rfc/rfc3514.txt

[PLANET] Planet Suricata : http://planet.suricata-ids.org/

[SECUONION] Security Onion : http://securityonion.blogspot.de/