Les logiciels libres sont en général connus pour leur flexibilité, gratuité et robustesse. Que ce soient les éditeurs tels qu'emacs ou vim, ou encore le système d'exploitation Linux et le logiciel Apache, dont le couple est très présent en ce qui concerne les serveurs sur Internet.
Nous allons dans cet article l'avantage de pouvoir disposer des sources des logiciels pour pouvoir les modifier afin d'arriver à réaliser une opération complexe : visualiser de manière graphique des alertes de sécurité en temps réel, en utilisant une vue 3D.
Les différentes technologies impliquées sont Prelude, IDMEF, SWIG, Python, graphviz et rtgraph3d.
| [1] | http://www.prelude-ids.org |
| [2] | (1, 2) http://tools.ietf.org/rfc/rfc4767.txt |
| [3] | http://www.swig.org |
| [4] | http://www.python.org |
| [5] | http://www.graphviz.org |
| [6] | (1, 2) http://www.secdev.org/projects/rtgraph3d |
Prelude est un système de détection d'intrusion (IDS) hybride : il combine les événements reçus par d'autres IDS, en particulier réseau (par exemple Snort ou NuFW) ou systèmes (vérification d'intégrité de fichier).
Il s'agit d'un logiciel libre, qui a été conçu en 1998 par Yoann Vandoorselaere, sur lequel est basée une offre de service commercial avec la société qu'il a fondé, Prelude IDS Technologies [7].
Le but de Prelude est de collecter et archiver tous les événements de sécurité, pour permettre d'alerter l'administrateur, mais aussi de pouvoir analyser l'historique d'un attaque et pouvoir retracer son déroulement. L'interface graphique d'analyse peut servir de console de supervision globale de la sécurité du réseau, avec un affichage en temps réel des alertes détectées.
Prelude transforme tous les événements au format IDMEF, format standard défini dans la RFC 4765. Cette standardisation nous sera utile par la suite, car elle permet d'accéder de manière unique aux informations décrivant une alerte : source, destination, gravité, etc.
L'architecture de Prelude se décompose comme suit :
- Des sondes, chargées de collecter les informations et d'envoyer des alertes par l'intermédiaire de la libprelude
- Un ou plusieurs centralisateurs (manager), qui collectent les alertes et les enregistrent dans une base de données
- Éventuellement, un moteur de corrélation
- Une interface graphique d'analyse
Il existe un grand nombre de sondes existantes qui fonctionnent déjà avec le système Prelude : Snort, le système de détection d'intrusions réseau; OSSEC, un système de détection d'intrusions machine; NuFW, le pare-feu authentifiant; ou encore des sondes fournies par le projet Prelude directement : Prelude LML, pour l'analyse des journaux; Prelude correlator pour l'analyse des différentes alertes reçues par les différentes sondes pour en déduire des alertes plus complexes. Si le sujet de la détection d'intrusions vous intéresse, vous pouvez allez consulter l'excellente page dédiée à son sujet sur wikipedia [8].
Ci-dessous, l'exemple d'une alerte complète au format IDMEF, correspondant à une tentative de connexion sur un utilisateur invalide :
alert:
messageid: 9420062158311
analyzer(0):
analyzerid: 1393164019714851
name: prelude-manager
manufacturer: http://www.prelude-ids.com
model: Prelude Manager
version: 0.9.10
class: Concentrator
ostype: Linux
osversion: 2.6.18-028stab045
node:
category: unknown (0)
location: 215
name: Master Manager
process:
name: prelude-manager
pid: 5629
path: /usr/sbin/prelude-manager
analyzer(1):
analyzerid: 1696989997938135
name: prelude-lml
manufacturer: http://www.prelude-ids.com
model: Prelude LML
version: 0.9.11
class: Log Analyzer
ostype: Linux
osversion: 2.6.18-028stab045
node:
category: unknown (0)
location: 215
name: Prelude test manager
process:
name: prelude-lml
pid: 26001
path: /usr/bin/prelude-lml
analyzer(2):
name: sshd
manufacturer: OpenSSH
class: Remote Login
node:
category: unknown (0)
name: prelude.inl.fr
address(0):
category: ipv4-addr (7)
address: 127.0.0.1
process:
name: sshd
pid: 11503
create_time: 11/01/2008 16:29:33.135789 +01:00
classification:
text: User login failed with an invalid user
detect_time: 11/01/2008 16:29:32.0 +01:00
analyzer_time: 11/01/2008 16:29:33.135828 +01:00
source(0):
spoofed: unknown (0)
node:
category: unknown (0)
address(0):
category: ipv4-addr (7)
address: 192.168.33.180
service:
iana_protocol_number: 6
iana_protocol_name: tcp
name: unknown
target(0):
decoy: unknown (0)
node:
category: unknown (0)
name: prelude.inl.fr
address(0):
category: ipv4-addr (7)
address: 127.0.0.1
user:
category: os-device (2)
user_id(0):
type: target-user (2)
name: GROSNAINDESBOIS
process:
name: sshd
pid: 11503
service:
iana_protocol_number: 6
iana_protocol_name: tcp
name: ssh
port: 22
assessment:
impact:
severity: medium (3)
completion: failed (1)
type: user (5)
description: Someone tried to login with the invalid user "GROSNAINDESBOIS" from 192.168.33.180
additional_data(0):
type: string (0)
meaning: Log received from
data: /var/log/auth.log
additional_data(1):
type: string (0)
meaning: Original Log
data: Jan 11 16:29:32 prelude sshd[11503]: Invalid user GROSNAINDESBOIS from 192.168.33.180
additional_data(2):
type: integer (4)
meaning: Rule ID
data: 1904
additional_data(3):
type: integer (4)
meaning: Rule Revision
data: 1
Comme vous le constatez, ce format IDMEF est exhaustif, et permet de traiter une alerte dans sa globalité. Ce que nous allons faire, c'est nous intéresser à différents chemins IDMEF comme par exemple alert.classification.text afin d'obtenir le nom de l'attaque.
Afin de comprendre ce qui est normalisé et ce que nous voulons utiliser, il faut comprendre ce format IDMEF, ce qui est le but de la partie suivante.
| [7] | http://www.prelude-ids.com |
| [8] | http://fr.wikipedia.org/wiki/Système_de_détection_d'intrusion |
IDMEF signifie "Intrusion Detection Message Exchange Format", qui se traduit en "Format d'Échange de Messages de Détection d'Intrusions". Il s'agit d'une norme disponible au sein de l'IETF sour forme de RFC [2].
Le format de messages est XML, qui offre de nombreux avantages :
Le format XML n'est cependant pas toujours adapté (notamment pour les performances), c'est pourquoi les messages sont souvent stockés dans un format binaire, et IDMEF sert principalement à l'échange des messages de manière standard.
Son modèle de données permet de faire face aux problématiques suivantes :
Dans IDMEF, chaque valeur est associée à un chemin, c'est-à-dire la séquence de clés permettant d'arriver jusqu'à l'élément. Certains éléments peuvent être des listes (la destination de l'attaque, par exemple).
Ce chemin permet de décrire facilement et de manière unique chacun des critères d'une attaque : le message de description se retrouve dans le chemin alert.classification.text, la sévérité potentielle dans alert.assessment.impact.severity, etc. Ce sont ces critères que nous allons représenter graphiquement.
L'utilisation d'un vocabulaire précis est importante : il permet aux utilisateurs de bien comprendre et aux développeurs de bien structurer leur programme. Passer le vocabulaire en revue nous permet aussi de comprendre les différentes fonctionnalités d'un système de détection d'intrusions réseau complet.
Nous vous proposons de suivre le chemin de vie d'une alerte, de sa naissance jusqu'à son enterrement.
Une alerte doit être conçue par trois éléments. Le premier est une source de données, qui est en fait une activité pouvant être une ligne de log, une description de politique de sécurité ou encore un paquet réseau. Une fois cette source reçue par la sonde, elle est envoyée à l'analyseur en vue d'extraire ce qui nous intéresse depuis la source, selon en général une suite de signatures.
Ensuite, les analyseurs envoient leurs résultats sous forme d'alerte IDMEF au concentrateur. Ce concentrateur stocke alors ces alertes en général dans une base de données. Il peut notifier l'opérateur, qui est en fait l'analyste de sécurité. Cet analyste peut donner des indications permettant d'avoir une réponse fiable face à la menace détectée.
La notification est intéressante, elle peut être filtrée par la corrélation (fait de regrouper un ensemble d'événements pour en déduire des alertes plus ciblées). Ainsi, comme dans l'image précédente, on peut remarquer une attaque correspondant non pas au fait qu'une connexion a échouée sur un utilisateur, mais sur une succession d'échecs. Ce qui correspond à un pirate cherchant certainement à essayer toute une série de mots de passe.
Nous allons ainsi récupérer la source, le type d'attaque et la destination. Mais avant d'arriver jusque là, nous allons vous présenter SWIG, qui nous a permis de modifier la libprelude afin de pouvoir utiliser facilement Python et créer un programme qui fait ce que nous voulons en quelques lignes de code.
SWIG (Simplified Wrapper and Interface Generator) est un outil permettant d'encapsuler un langage dans un autre, pour permettre par exemple d'utiliser des fonctions définies dans un langage bas niveau tel que C, dans un langage de haut niveau, tel que Python ou Perl. SWIG supporte la conversion vers une dizaine de langages environ.
Nous allons utiliser SWIG pour créer une couche d'abstraction autour de la librairie Prelude. Pour pouvoir effectuer des développements rapides, il est en effet très utile de pouvoir disposer d'un langage interprété de haut niveau :
- exécution interactive
- pas de gestion de la mémoire nécessaire
- risque d'erreurs réduit, grâce aux nombreuses vérifications
- faible quantité de code pour effectuer des actions complexes
- code orienté objet
- nombreuses librairies disponibles
Avant de pouvoir utiliser SWIG, il s'est révélé utile de créer une couche d'abstraction C++. SWIG permet d'exploiter les fonctions objet de ce langage efficacement, et de les convertir de manière native dans le langage cible.
Exemple:
class IDMEF {
protected:
idmef_message_t *_message;
public:
IDMEF() throw (const char *);
int Set(const char *object, const char *value);
char * Get(const char *object) throw (const char *);
};
Chaque fonction effectue des opérations complexes (ici, création d'une valeur IDMEF associée à un chemin)
int IDMEF::Set(const char *object, const char *value)
{
int ret;
idmef_path_t *path;
idmef_value_t *val;
ret = idmef_path_new(&path, object);
if (ret < 0)
return ret;
ret = idmef_value_new_from_path(&val, path, value);
if (ret < 0 ) {
idmef_path_destroy(path);
return ret;
}
ret = idmef_path_set(path, _message, val);
idmef_value_destroy(val);
idmef_path_destroy(path);
return 0;
}
SWIG utilise un fichier décrivant les fonctions à encapsuler. De manière typique, ce fichier va inclure le code C++
%module PreludeEasy
%{
#include "easy-idmef.h"
%}
%include easy-idmef.h
Ce fichier permet de contrôler de manière précise le code que SWIG va générer, s'il y a des conversions de type de données à effectuer, etc.
La compilation de ce fichier par SWIG donne plusieurs fichiers (ici, en python):
swig -c++ -DPRELUDE_PYTHON -python -o easy-idmef_wrap_python.cxx swig/libprelude-easy.i
On obtient deux fichiers :
- easy-idmef_wrap_python.cxx : le code C++ du module, qu'il faut compiler
- PreludeEasy.py : le code python du module, qui fait le lien avec ce code C++
Après compilation des fichiers obtenus par SWIG, le module est prêt à être installé et utilisé. On l'utilise comme un module standard Python
import PreludeEasy
idmef = PreludeEasy.IDMEF()
idmef.Set("alert.classification.text","Message")
print idmef.Get("alert.classification.text")
Le même code, en langage C, aurait pris plusieurs dizaines de lignes ! Grâce à l'utilisation de SWIG, nous pouvons désormais exploiter la puissance du langage Python pour développer rapidement un programme combinant Prelude et des librairies de visualisation 3D.
Attention tout de même, les bindings [9] sous leur forme actuelle sont encore en phase de développement intensif et ne sont supportés que de manière expérimentale par le projet Prelude.
| [9] | http://www.wzdftpd.net/trac/wiki/Misc/PreludeEasy |
Grâce aux éléments vus dans les parties précédentes, nous avons les clés pour comprendre ce qu'il faut pour réaliser la fonction qui nous intéresse : visualiser en temps réel une attaque.
Tout d'abord, cette visualisation se fera en 2D en utilisant graphviz. Ensuite, nous allons voir comment modifier un programme existant pour adapter ce code graphviz (langage dot) à un système de visualisation 3D.
Graphviz est un système qui permet à partir d'un langage de description de produire une image dans des formats bitmaps (gif, png, jpg, ...) comme vectoriels (svg, ps, ...). Il est même possible de décrire la position des noeuds au format MAP compréhensible par du code HTML afin de rendre les images cliquables précisément par rapport aux noeuds posés.
Il s'agit du langage permettant de simplement décrire les graphes que vous souhaitez réaliser.
Par exemple, le code dot suivant :
digraph G {
node1 [label="Foo",color="red"];
node2 [label="Bar",color="green"];
node1 -> node2;
}
Produit, grâce a la commande dot -Tpng graph.dot > graph.png le graphe suivant :
Le langage dot est relativement structuré : les attributs des noeuds comme ceux des liens sont placés devant leur déclaration.
Afin de simplifier la création du code dot, nous utiliserons la classe Python GvGen [10]. De cette façon, il est aisé de réaliser des graphes complexes : il ne suffit que de déclarer les différents objets et de poser leur relations.
Par exemple, si nous souhaitons créer un graphe avec une légende, le code dot devient compliqué parce que par défaut, graphviz ne sait pas gérer ce cas. Il faut en effet supprimer la flèche, tout en imposant une direction au graphe afin que le texte s'affiche à droite de l'élément que nous voulons mettre en légende, puis supprimer le lien et éviter de d'entourer le texte de description.
Voici le code GvGen permettant de générer un graph simple avec une légende :
#!/usr/bin/python
import gvgen
# Création d'un nouveau graphe avec une légende
graph = gvgen.GvGen("Legend")
# Création des items "foo" et "bar"
a = graph.newItem("foo")
b = graph.newItem("bar")
# Lier "foo" avec "bar"
graph.newLink(a,b)
# Création et application des styles
graph.styleAppend("foostyle","color","red")
graph.styleAppend("foostyle","shape","rectangle")
graph.styleApply("foostyle", a)
graph.styleAppend("barstyle","color","blue")
graph.styleAppend("barstyle","style","filled")
graph.styleApply("barstyle", b)
# Création d'une zone de légende
graph.legendAppend("foostyle", "Foo item")
graph.legendAppend("barstyle", "This is the bar item")
# Création du code dot
graph.dot()
Le code précédent va générer le code dot suivant :
digraph G {
compound=true;rankdir=LR;
subgraph cluster1 {
label="Legend";
node7 [shape="plaintext",label="This is the bar item"];
node6 [color="blue",style="filled",label=""];
node5 [shape="plaintext",label="Foo item"];
node4 [color="red",shape="rectangle",label=""];
}
node2 [color="red",shape="rectangle",label="foo"];
node3 [color="blue",style="filled",label="bar"];
node6->node7 [style="invis",dir="none"];
node4->node5 [style="invis",dir="none"];
node2->node3;
}
On remarque de le code python avec GvGen nous permet d'automatiser la création du langage dot, mais aussi de rendre sa création plus simple à l'aide de fonctions n'existant pas dans graphviz, comme les définitions de styles.
Ce code dot permet de créer l'image suivante :
Si vous souhaitez voir un excellent exemple d'application utilisant GvGen, vous pouvez vous tourner vers Graphdep [11], un outil d'affichage de dépendances entre fonctions dans du code C, C++ ou python.
Prelude, comme vu au début de l'article, permet de récupérer grâce au système de polling toutes les alertes que les différentes analyseur ont pu lui envoyer.
Grâce aux bindings faciles, nous pouvons récupérer tous les objets IDMEF souhaités pour les passer à GvGen. Le but étant d'arriver au graphe 2D permettant de visualiser des attaques.
Nous allons récupérer les cibles afin de regrouper les attaques avec des jeux de couleurs représentant la gravité de chacune des attaques.
C'est en récupérant une branche spécifique de Prelude que nous allons pouvoir développer facilement l'affichage des attaques en langage dot.
Rtgraph3d [6] à été développé par Philippe Biondi dans le bus d'offrir une application équivalente à graphviz, mais en 3D et en temps réel.
DBus est utilisé pour pouvoir se connecter et interagir avec l'application en envoyant une simple chaine de texte.
Sachant que nous avons déjà réussi à générer le code dot, il serait fâcheux de reprendre tout le travail. Il est donc plus simple de modifier le code de rtgraph3d afin d'y ajouter l'import graphviz.
Pour se faire, nous allons utiliser pydot, qui permet de lire le code dot et de le transformer en objets Python. L'algorithme utilisé sera le suivant :
Pour chaque lien :
Pour chaque noeud du lien :
Si c'est la source :
label_source = attribut label du noeud
couleur_source = attribut color du noeud
Si c'est la destination :
label_dest = attribut label du noeud
couleur_dest = attribut color du noeud
Si nous n'avons aucun label pour les sources :
Attribuer le nom du lien pour le noeud
Création du noeud source nommé et avec la couleur normalisée
Création du noeud destination nommé et avec la couleur normalisée
Si la couleur est mise en paramètre, mettre à jour les noeuds
Et en appliquant le patch suivant, on peut maintenant utiliser la fonction d'import dot dans rtgraph3d :
--- rtg_cli.py.orig 2008-01-10 19:20:30.000000000 +0100
+++ rtg_cli.py 2008-01-10 19:19:47.000000000 +0100
@@ -94,6 +154,35 @@
for n1,n2 in zip(e[:-1],e[1:]):
self.rtg.new_edge(n1,{},n2,{})
+ def do_dot(self, args):
+ graph = pydot.graph_from_dot_file(args)
+ for edge in graph.get_edge_list():
+ edge_src = "\"" + edge.get_source() + "\""
+ edge_dst = "\"" + edge.get_destination() + "\""
+ for node in graph.get_node_list():
+ if node.name == edge_src:
+ src_label = node.get_label()
+ src_color = node.get_color()
+ if node.name == edge_dst:
+ dst_label = node.get_label()
+ dst_color = node.get_color()
+
+ if not src_label:
+ src_label = edge.get_source()
+
+ if not dst_label:
+ dst_label = edge.get_destination()
+
+
+ edge_args = src_label + " " + dst_label
+ self.do_edge(edge_args)
+ if src_color:
+ src_color_s = src_label + " color=" + color_normalize(src_color)
+ self.do_update(src_color_s)
+ if dst_color:
+ dst_color_s = dst_label + " color=" + color_normalize(dst_color)
+ self.do_update(dst_color_s)
+
def do_glow(self, args):
for n in args.split():
self.rtg.glow(n)
Pour la normalisation des couleurs, nous utilisons la fonction color_normalize qui est disponible à l'adresse suivante: http://www.wallinfire.net/files/color_calc.py
Maintenant que nous avons tout ce code, il ne nous reste plus qu'à faire le code Prelude qui fait le lien entre :
- Une attaque que nous produisons volontairement : un scan de ports, un utilisateur qui se trompe de mot de passe, etc..
- Une sonde Prelude qui détecte cette attaque
- Notre code qui récupère les objets que le collecteur reçoit des sondes
- Graphviz, que nous utilisons avec GvGen pour générer du code dot
- RtGraph3d que nous utilisons avec le patch mis plus haut pour avoir une vue en 3D des attaques
Voici le code que nous allons utiliser pour produire le graphe. Il est montré ici par morceaux, mais il est disponible en libre téléchargement à l'adresse : http://svn.prelude-ids.org/libprelude/branches/libprelude-easy-bindings/bindings/tools/idmef-path-gvgen.py
Tout d'abord, on crée le client avec ce code :
import PreludeEasy
client = PreludeEasy.Client("PreludeGvGen")
client.Init()
client.PoolInit("192.168.33.215", 1)
Le nom de notre client est "PreludeGvGen", cela veut dire qu'il faut l'enregistrer avec les capacités IDMEF de lecture sur le collecteur. On le fait en tapant sur la machine qui sera utilisée pour lancer l'application de cette façon :
~# prelude-admin register "PreludeGvGen" "idmef:r" 192.168.33.215 --uid 1000 --gid 1000
Puis, sur le collecteur :
~# prelude-admin registration-server prelude-manager
Une fois la sonde enregistrée pour l'utilisateur ayant le numéro 1000, on peut l'utiliser en tant que simple utilisateur.
La fonction de lecture d'objets IDMEF est initialisée à l'aide de la fonction PoolInit.
Maintenant, nous pouvons faire une boucle infinie pour la lecture de chaque objet IDMEF que le collecteur verra :
while 1:
idmef = client.ReadIDMEF(1)
if idmef:
handle_alert(idmef)
C'est la fonction ReadIDMEF permet de lire un message IDMEF que le collecteur de Prelude lui aura envoyé.
Nous définissons comme fonction de callback handle_alert, qui est définie comme ce qui suit :
def handle_alert(idmef):
source = idmef.Get("alert.source(0).node.address(0).address")
if not sourceslist.has_key(source):
sourceitem = graph.newItem(source)
sourceslist[source] = sourceitem
target = idmef.Get("alert.target(0).node.address(0).address")
if not targetslist.has_key(target):
targetitem = graph.newItem(target)
targetslist[target] = targetitem
alert = idmef.Get("alert.classification.text")
alert = alert.replace(' ','_')
if not alertslist.has_key(alert):
alertitem = graph.newItem(alert)
alertslist[alert] = alertitem
severity = idmef.Get("alert.assessment.impact.severity")
if severity:
if severity == "high":
graph.propertyAppend(alertslist[alert],"color","red")
graph.propertyAppend(alertslist[alert],"style","filled")
if severity == "medium":
graph.propertyAppend(alertslist[alert],"color","orange")
graph.propertyAppend(alertslist[alert],"style","filled")
if severity == "low":
graph.propertyAppend(alertslist[alert],"color","green")
graph.propertyAppend(alertslist[alert],"style","filled")
if severity == "info":
graph.propertyAppend(alertslist[alert],"color","blue")
graph.propertyAppend(alertslist[alert],"style","filled")
graph.newLink(sourceslist[source],alertslist[alert])
graph.newLink(alertslist[alert],targetslist[target])
Il s'agit tout simplement de la fonction principale, qui gère la récupération de la source, destination ainsi que le nom de l'alerte pour utiliser les fonctions de GvGen pour produire le graphe en langage dot.
Nous allons utiliser un signal de terminaison pour produire le graphe. Par exemple un simple kill ou Ctrl-C permettra de l'afficher :
def sighandler(sig, frame):
graph.dot()
sys.exit(0)
signal.signal(signal.SIGTERM, sighandler)
signal.signal(signal.SIGINT, sighandler)
Maintenant nous pouvons lancer notre programme :
$ ./idmef-path-gvgen.py
Puis nous appuyons sur Ctrl+C, et nous voyons :
digraph G {
compound=true;
node1 [label="192.168.33.180"];
node2 [label="127.0.0.1"];
node3 [color="orange",style="filled",label="User_login_failed"];
node4 [label="192.168.33.215"];
node5 [color="green",style="filled",label="(portscan)_TCP_Portscan"];
node6 [label="10.8.0.46"];
node7 [color="orange",style="filled",label="Server_recognition"];
node8 [label="192.168.33.139"];
node9 [color="orange",style="filled",label="User_login_failed_with_an_invalid_user"];
node1->node3;
node1->node5;
node3->node2;
node5->node4;
node6->node7;
node7->node2;
node8->node9;
node8->node3;
node9->node2;
}
Ce qui nous donne, à l'aide d'un dot -Tpng gvgen-2d.dot > gvgen-2d.png :
Le graphe se lit en regardant les noeuds en haut, qui sont les sources. Nous avons donc été attaqués par trois sources différentes. Au milieu, ce sont les attaques, avec un jeu de couleur en fonction de la gravité. Puis, en bas nous avons les cibles. Il y en a deux : 127.0.0.1 et 192.168.33.215.
192.168.33.215 est l'adresse IP réseau de la machine et 127.0.0.1 aussi, mais il s'agit de l'adresse IP locale. Si l'on voit cette adresse IP, c'est simplement parce que cela correspond à la cible vue par Prelude LML lors de l'analyse de log. Cette adresse peut bien sur se configurer.
Maintenant, grâce au patch sur RTgraph3d, nous allons pouvoir visualiser en 3D ces mêmes évènements grâce à l'import dot.
Nous lançons donc la fenêtre OpenGL de rtgraph3d :
$ ./rtgraph3d.py &
Puis son programme client :
$ ./rtg_cli.py
Nous pouvons taper notre commande "dot", qui correspond à l'import dot de notre graphe :
RTG> dot gvgen-2d.png
Ce qui nous donne l'image suivante :
| [10] | http://software.inl.fr/wiki/GvGen |
| [11] | http://haypo.hachoir.org/trac/wiki/graphdep |
Le modèle de développement des logiciels libres permet à tous de pouvoir contribuer aux applications de manière très simple : par l'ajout de fonctionnalités, la documentation, les traductions etc.
Nous tenons à remercier tous les acteurs de cette communauté qui nous ont permis d'obtenir des connaissances, qui nous servent depuis tous les jours dans notre travail.
La 3D offre une alternative intéressante aux représentations graphiques habituelles. Elle permet, par une disposition judicieuse des éléments, de présenter les informations différemment, de mieux pouvoir comprendre les relations entre chaque élément.
Grâce aux modifications et améliorations apportées aux logiciels, la représentation graphique des alertes est maintenant accessible facilement. Ceci apporte des possibilités intéressantes, qui devront être explorées pour pouvoir représenter des informations pertinentes dans le but d'aider l'utilisateur à mieux comprendre les attaques détectées.