Vous êtes sur la page 1sur 18

Outils statistiques pour la fouille de fichiers

de logs

Yves Agostini
RSSI - Université de Lorraine
34 Cours Léopold
54 000 Nancy

Résumé
Après un rapide rappel des notions élémentaires de statistiques puis une introduction au logiciel opensource
R, cet article abordera la fouille de données de divers types de fichiers de traces à l’aide de méthodes
statistiques.
Les objectifs sont la recherche d’évènements anormaux à titre préventif ou la recherche d’indicateurs de
compromission.
Nous verrons que l’approche statistique est de nature forcément imprécise et qu’il n’y a pas de méthodologie
absolue dans la conduite d’une fouille de données. Cependant les résultats obtenus permettent de mettre en
œuvre des procédures de détection complémentaires au simple comptage d’évènement.

Mots clefs
Data Mining, Sécurité, Big Data, log, statistiques

1 Introduction
Il existe depuis longtemps un grand nombre d’outils pour traiter les fichiers de logs. On peut citer le
vénérable awstats, largement déployé dans la communauté d’administrateurs systèmes. Piwik pour les
serveurs web, qui clone les fonctionnalités de GoogleStats, ou encore le plus moderne et très performant
Kibana capable d’exploiter les données gérées et stockées par Logstach et ElasticSearch. Cependant
ces outils utilisent essentiellement du comptage d’évènements. De la même façon des outils d’alertes très ré-
pandus comme logwatch ou fail2ban se limitent à la détection d’évènements par expression régulière et
comptage. Les seuils d’alertes y sont positionnés empiriquement. Les évènements furtifs à l’origine d’inci-
dents de sécurité se retrouvent souvent masqués dans le grand nombre d’évènements réguliers et récurrents.
Cet article vise à aborder un certain nombre de méthodes statistiques pour analyser des journaux d’évène-
ments volumineux. Il s’agit dans un premier temps d’analyser des fichiers aussi divers que des logs ldap, des
logs de connexions, des logs d’attaques en force brute. Les travaux en cours permettront peut-être d’aborder
les logs de messagerie ou de flux netflow.
Ces analyses ont pour objectif principal de détecter les évènements potentiellement anormaux lors d’une
étude préventive de la qualité des services. Ces évènements peuvent être des indicateurs de compromission.
Cette fouille de données est effectuée sur des données statiques. Les résultats des ces fouilles peuvent
permettre d’implémenter des algorithmes de détection en temps réel.

JRES 2015 - Montpellier 1/18


L’essentiel des opérations d’analyse sont réalisées avec le framework opensource de statistiques R. Ce
framework est largement utilisé dans le monde scientifique, dans des domaines aussi divers que l’archéolo-
gie, la biologie, l’analyse financière ou la représentation de données géographiques[1]. Il existe une commu-
nauté très active avec de très nombreux forums, blogs, tutoriaux. Cependant la diversité des thèmes traités
fait qu’il est difficile de trouver une information adaptée à nos problématiques d’administrateurs systèmes.

2 Notions élémentaires de statistiques


Nos pratiques du numérique nous donnent rarement l’occasion de réutiliser les notions de statistiques ac-
quises lors de nos formations généralement scientifiques. De nos jours, on retrouve facilement sur Internet
la longue liste de formules mathématiques que nous avons plus ou moins péniblement assimilé dans notre
jeunesse. Je ne les répèterai pas ici. Je vais plutôt illustrer les notions de base comme la moyenne, la mé-
diane, la covariance ou encore la validité des tests à partir d’un exemple concret qui ne nécessitera pas de
long calculs.
Notre exemple est constitué de trois jeux de notes et de deux groupes d’étudiants. Vous pouvez imaginer
qu’il s’agit de groupes d’étudiants à qui vous donnez des cours ou des notes de vos jumeaux (private joke
inside).
Le premier jeu de notes est constitué des valeurs : 1, 9, 10, 11, 19. Le second, des valeurs : 8, 9,
10, 11, 12. Le troisième contient : 4.0, 4.5, 5.0, 5.5, 6.0.
Faites une petite pause et observez bien les caractéristiques de ces valeurs. Elles sont volontairement imag-
inaires pour être faciles à retenir et permettre des calculs «de tête».
Le souvenir de vos propres résultats scolaires vous permet de facilement calculer les moyennes de ces trois
séries de notes. À partir de la seconde série : la moyenne de 8 et 12, est 10. De la même façon la moyenne
de 9 et 11, est 10 et si on obtient encore un 10 la moyenne générale est de 10. Cela correspond à la formule
de la somme des notes divisée par leur nombre. Les moyennes des trois séries de notes sont alors : 10, 10
et 5.
Il est maintenant temps de s’interroger sur l’utilité de cette information et plus particulièrement quelle
réalité elle représente.
Si les valeurs sont imaginaires, je vous ai volontairement présenté le problème comme il se présente souvent
dans le monde réel : le contexte est mal défini et incomplet. On ne sait pas à quel groupe d’étudiant
appartient chaque série de notes, ni si la troisième série est notée sur 10 ou sur 20. Nous allons étudier ces
valeurs pour proposer des hypothèses qui permettent de préciser le contexte de ces résultats notés.
Une première réponse naïve consiste a interpréter littéralement les valeurs des moyennes trouvées : le
premier groupe a 10 de moyenne, le second 5.
Cette approche littérale pose un problème supplémentaire. Imaginons une erreur de saisie. L’opérateur a
saisi 190 au lieu de 19 : la moyenne devient alors 44.2. Nous ne sommes plus capable de proposer une
réponse à notre problème d’identification de ces séries de notes.
La solution pour éviter ce nouveau problème est d’utiliser la «médiane». C’est un calcul de moyenne après
avoir exclu les valeurs extrêmes 1 . On obtient alors 10. La médiane est alors une meilleure estimation que
la moyenne pour nos valeurs. La médiane est plus robuste que la simple moyenne.
Observons maintenant attentivement les deux séries qui ont 10 de moyenne (ou de médiane). On se rend
rapidement compte que pour une même moyenne la dispersion des valeurs est très différente. Utiliser seule-
ment la valeur obtenue par la moyenne ne permet pas de s’en rendre compte.
1. Il s’agit ici de l’usage de la médiane et non de sa définition mathématique

JRES 2015 - Montpellier 2/18


L’«écart type» (ou «déviation standard») est une bonne mesure de la dispersion des valeurs. L’écart type
des 3 valeurs : 1, 10, 19 est 9. L’écart type des 3 valeurs : 8, 10, 12 est de 2. Comme l’écart type est une
distance des diverses dispersions (racine carré de la «variance» qui est une moyenne des dispersions au
carré 2 ), on obtient respectivement pour nos trois séries de 5 valeurs : 6.40, 1.58, 0.79. La première
série a un écart type beaucoup plus important que les deuxième et troisième séries. On peut alors proposer
comme hypothèse que la première série appartient au premier groupe et que les deux séries suivantes
pourrait appartenir au second groupe. Il faut cependant encore s’interroger sur la différence entre les
écarts types des deux dernières séries.
Les écarts types sont différents parce qu’ils sont calculés à partir des valeurs brutes de nos séries. Cependant
nous ne savons pas si la troisième série est notée sur 10 ou sur 20. On pourrait «centrer» ces valeurs avant
traitement (les uniformiser sur 20). Nous allons plutôt calculer leur «corrélation».
La corrélation est calculée à partir de la covariance : une comparaison entre les variances des valeurs
centrées. Il faut alors calculer les corrélations entre chaque série de valeurs deux à deux 3 .
La corrélation entre notre première et seconde série est identique à la corrélation entre la première et le
troisième série. Sa valeur est de 0.94. La corrélation entre la seconde et troisième série est de 1 : nous
avons une corrélation totale. Il est alors fort probable que notre première série de notes appartient au
premier groupe et que les deuxième et troisième séries appartiennent au second groupe, contrairement à
ce que laissait imaginer le seul examen des moyennes. Nous pouvons alors interpréter le second groupe
comme un groupe d’étudiants aux résultats homogènes. Le premier groupe étant un groupe contenant des
étudiants ayant de très bon résultats avec des étudiants ayant de très faibles résultats.
Ces premières notions nous permettent déjà de nous rendre compte qu’une étude statistique des valeurs col-
lectées nous apporte des informations complémentaires sur leur contexte. Cependant il apparaît également
qu’un certain nombre de précautions doivent impérativement être pris compte :
– Un seul critère pour examiner une série de valeurs n’est pas suffisant. Une moyenne sans écart type
n’a pas beaucoup de sens (comme les multiples sondages qui essaient d’illustrer «ce que pensent les
français»).
– Il faut impérativement une connaissance du domaine traité pour choisir les meilleurs outils de traite-
ment. La médiane serait un mauvais choix s’il n’y pas de risque d’erreur de saisie. Inversement, il
peut être nécessaire de corriger les données traitées pour enlever d’éventuelles valeurs aberrantes.
– La corrélation masque plusieurs traitements mathématiques. Dans notre cas, en centrant implicite-
ment les valeurs de la troisième série, nous émettons l’hypothèse qu’il s’agit de notes sur 10 et non
sur 20. Il ne faut jamais oublier que la corrélation reste un indicateur et n’implique pas forcément une
causalité.
– L’absence ou le manque de valeurs doivent amener à une absence de décision plutôt qu’à une inter-
prétation littérale des valeurs calculées.
Lorsque l’on étudie deux séries de valeurs d’autres outils sont régulièrement utilisés. L’outil le plus courant
est la «régression linéaire» : il s’agit de trouver la droite qui passe au mieux entre les valeurs de notre
distribution de données. Ainsi si l’on effectue une régression linéaire entre nos séries de valeurs corrélées,
on trouve très logiquement une droite de coefficient directeur 2.0 (la «pente» ou «slope» en anglais) et une
ordonnée à l’origine de 0 («décalage» ou «intercept» en anglais). 4
La régression linéaire est un modèle de distribution de données. D’autres modèles sont possibles. Par ex-
emple, lorsque l’on dispose de données qualitatives (présence ou absence d’un attribut) au lieu de données
quantitatives comme dans notre exemple, on peut imaginer que le modèle est une distribution aléatoire
2. Il est inutile de retenir cette formule qui est essentiellement destinée à simplifier les manipulations mathématiques
3. On peut représenter ces résultats par une matrice de corrélations symétrique sur la diagonale
4. Attention : en France on représente traditionnellement une droite sous la forme y = ax + b alors que le monde anglo-saxon
utilise plutôt y = a + bx

JRES 2015 - Montpellier 3/18


normale. Divers tests peuvent être calculés pour évaluer la correspondance entre nos données et le modèle.
On obtient une probabilité de correspondance («p-value»). Le test du χ2 est souvent utilisé pour des valeurs
qualitatives. On peut utiliser une étude de la variance (ANNOVA) pour évaluer une régression linéaire. Ces
modèles vont permettre de détecter les valeurs suspectes.
Cette introduction aux statistiques n’a pas pour objectif d’être un cours complet. Nous avons dorénavant
suffisamment d’éléments pour comprendre les enjeux statistiques des exemples de traitements de fichiers
de traces.

3 Logiciel R
R est un logiciel opensource largement utilisé dans des communautés très diverses. Comme il s’utilise
principalement en ligne de commande, à partir de son interface shell, cela doit plaire à notre communauté
d’administrateurs systèmes. On y retrouve la possibilité de rappeler l’historique de ses commandes, de
les copier dans une fichier texte ou encore de créer un script commenté. Il s’installe facilement sur les
distributions linux à partir de dépôts de paquets.
Vous trouverez de nombreux tutoriels pour vous initier à R[2]. Je ne présenterai dans cet article que les
éléments nécessaires à la compréhension des exemples de cet article.

3.1 Type de données

R est un langage interprété où il n’est pas nécessaire de déclarer ses variables. Le premier élément inhabituel
est l’opérateur d’affectation qui est <-. Le symbole = est plutôt utilisé pour les affectations des paramètres
de fonction. Ainsi, a <- 5 + 2 affecte la valeur 7 à la variable a.
Dans R tout est objet et R manipule des vecteurs d’objets de même type. On peut noter que l’indice des
vecteurs commence à 1 contrairement au 0 des langages dérivés de C.

> notes1 <- c(1, 9, 10, 11, 19) # c() concat ène les valeurs
> mode( notes1 ) # type de données
[1] " numeric "
> length ( notes1 ) # longueur du vecteur
[1] 5
> notes1 [3] # accès à la valeur d’ indice 3
[1] 10
> label <- c(’aa ’,’bb ’ ,42) # un vecteur de chaine de caract ères
> mode(label)
[1] " character "
> label [2] # accès à la valeur d’ indice 2
[1] "bb"
> label [3]
[1] "42"
> mode(label [3]) # 42 n’est pas numérique
[1] " character "

Les tableaux peuvent avoir de multiples dimensions. Nous allons voir ci-dessous quelques exemples de
manipulation d’un tableau standard à deux dimensions avec la fonction matrix. Les paramètres nrow et
ncol définissent la taille du tableau. Les valeurs sont créés par la séquence 1:6. L’option binaire byrow
définit l’ordre d’affectation.

JRES 2015 - Montpellier 4/18


> t <- matrix (1:6 , nrow = 2, ncol = 3, byrow = TRUE) # affectation
> t # visualisation
[ ,1] [,2] [,3]
[1 ,] 1 2 3
[2 ,] 4 5 6
> colnames (t) <- c(’aa ’,’bb ’,’cc ’) # dé finition du nom des colonnes
> t # visualisation
aa bb cc
[1 ,] 1 2 3
[2 ,] 4 5 6
> t[2 ,] # accès par ligne
aa bb cc
4 5 6
> t[ ,1] # accès par colonne
[1] 1 4
> t[,’aa ’] # accès par le nom de la colonne
[1] 1 4

Les listes permettent de créer des vecteurs contenant des modes (ou types) différents.

> l <- list (1:6,’a’,’b’) # liste contenant des numé riques et des caract ères
> names(l) <- c(’r’,’s’,’t’) # nommage des éléments
> l
$r
[1] 1 2 3 4 5 6
$s
[1] "a"
$t
[1] "b"
> mode(l) # type liste
[1] "list"
> mode(l$r) # sous type numeric
[1] " numeric "
> l$t # acces à t
[1] "b"
> l$r [3] # accès au 3ème élément de r
[1] 3

Pour finir les data.frame permettent de créer des tableaux contenant de données de modes (ou types)
variables 5 . Notez à la fin de l’exemple ci-dessous quelques exemples des fonctions statistiques les plus
courantes.

> df <- data.frame( notes2 = c(8 ,9 ,10 ,11 ,12) , notes3 = c(4 ,4.5 ,5 ,5.5 ,6) ,
el = c(’a’,’b’,’c’,’d’,’e ’))
> df
notes2 notes3 el
1 8 4.0 a
2 9 4.5 b
3 10 5.0 c

5. Le paquet data.table permet une conversion des data.frame. Il apporte un gain de performance sur les gros volumes de données
et une syntaxe de sélection simplifiée

JRES 2015 - Montpellier 5/18


4 11 5.5 d
5 12 5.0 e

> cor(df$notes2 , df$notes3 ) # corré lation des notes2 et notes3


[1] 1

> lm( df$notes2 ~ df$notes3 ) # ré gression linéaire


> mean( df$notes2 ) # moyenne
> median ( df$notes2 ) # médiane
> sd( df$notes2 ) # standard deviation : écart type

3.2 Lecture des données

Même s’il existe des connecteurs aux bases de données, les données à traiter sont habituellement lues
depuis un fichier texte. Il suffit d’indiquer le séparateur de colonnes. Dans certains cas on peut alors injecter
directement un fichier de log si le séparateur est bien identifié. Sinon perl sera votre ami pour préparer votre
fichier de données. On utilisera alors couramment un format csv.
La commande suivante : log <- read.csv("slapd-logs.txt",sep=";") permet de lire un fichier
slapd-logs.txt et de l’affecter directement sous forme de data.frame dans la variable log.
La commande summary(log) essaie de résumer l’essentiel des données de la variable log. On peut ainsi
rapidement s’assurer de la cohérence de ces données.

3.3 Structures de contrôle

R est un langage riche qui permet d’écrire des fonctions et dispose naturellement des structures de contrôle
classiques comme if, else, switch ou de boucles comme while, for, foreach. Cependant R a été
spécialement conçu pour les performances et le calcul matriciel en travaillant sur des structures de données
en mémoire. Il s’agit alors de manipuler directement les colonnes ou les lignes des data.frame. Par exemple
comme, ci-dessous, à l’aide des fonctions spéciales X apply.

# Multiplication de toutes les notes par 2, sans boucle de contrôle


> sapply (df [ ,1:2] ,"*" , 2)
notes2 notes3
[1 ,] 16 8
[2 ,] 18 9
[3 ,] 20 10
[4 ,] 22 11
[5 ,] 24 12
> sapply (df$notes2 ,"*" ,2)
[1] 16 18 20 22 24

3.4 Packages

La commande source permet d’inclure un fichier contenant nos fonctions. Lorsque ces fonctions sont
suffisamment génériques et documentés elles peuvent être inclus dans le dépôt communautaire CRAN :
Comprehensive R Archive Network. C’est une source de référence qui permet d’éviter de redévelopper des
fonctions déjà existantes.

JRES 2015 - Montpellier 6/18


Les distributions Linux fournissent en général un certain nombre de packages pré-compilés. La commande
install.packages("...") permet de les télécharger depuis les miroirs du dépôt CRAN. On les charge
ensuite en mémoire avec la commande library("...").
Pour augmenter leur performance un certain nombre de paquets sont écrits en C. Il est alors nécessaire de
disposer d’une chaine de développement complète pour installer ces paquets.
Nous verrons dans les exemples de fouilles de données plusieurs exemples de visualisations graphiques.

4 Data Mining
Maintenant que nous possédons quelques bases de statistiques et d’utilisation du logiciel R, nous pouvons
nous lancer dans la fouille de données (Data Mining) de nos fichiers de traces.

4.1 Colinéarité

L’analyse de données commence généralement par les analyses classiques de corrélation et la détection
graphique des premières anomalies évidentes dans la distribution des données.

Figure 1 - Scatterplot d’un fichier de log Openldap

Ce type de tableau (figure 1) permet de visualiser rapidement la distribution des données (panneau du bas).
La diagonale fait apparaitre l’histogramme. Le panneau du haut fournit les coefficients de corrélation entre

JRES 2015 - Montpellier 7/18


chaque type de données collectées.
Le code permettent de générer cette image est extrêmement simple :

> log <- read.csv (" slapd -logs.txt",sep =";")


> source (" pannels .R")
> pairs(log , lower.panel = panel.smooth , upper.panel = panel.cor ,
diag.panel = panel.hist)

Nous remarquons tous de suite une forte corrélation entre la colonne id et la colonne time. Lorsque l’on
connait la structure des logs openldap cette corrélation est toute à fait normale puisque id est l’identifiant
de chaque connexion. On a alors une corrélation non significative qui indique une information presque
redondante. Cette colonne peut être éliminée avec la commande log$id <- NULL

4.2 Clustering

Une des premières particularités des fichiers de logs est qu’ils contiennent essentiellement des données
qualitatives. Le comptage est la méthode la plus simple pour traiter ces données.
R permet d’envisager d’obtenir rapidement des tableaux de comptages multi-dimensionnels qui permettent
de répondre à des questions comme : «quelles IPs effectuent quelles opérations ldap ?».
À partir d’un certain nombre de lignes et de colonnes ces tableaux de comptages deviennent difficiles à
interpréter. Une première approche est de grouper ces résultats pour identifier par exemple les IPs effec-
tuant des opérations similaires. Nous pouvons alors utiliser des techniques de clustering pour afficher les
groupements. La figure 2 ci-dessous illustre trois représentations d’un classement par arbre de décision.
Le package rpart permet d’afficher les critères de regroupement. Le graphique coloré utilise le package
igraph. Les machines générant beaucoup d’erreurs ou limitées à des requêtes de recherche apparaissent très
rapidement.

# Arbre de dé cision
> library (rpart.plot)
Le chargement a né cessit é le package : rpart

> help(rpart.plot) # aide en ligne


...

> arbre <- rpart(ip ~ op ,log) # IPs par opé rations


> arbre2 <- rpart(op ~ ip ,log) # opé rations par IPs

# affichage type 5
> prp(arbre , branch .type =5, faclen =0, varlen =0, yesno=FALSE)

# affichage type 4
# fonction de traitement des labels
> split.fun <- function (x, labs , digits , varlen , faclen )
{gsub (" = " ,":\n",labs )}
> prp(arbre2 ,type =4, extra =100 , split.fun=split.fun ,tweak =.8, varlen =0, faclen =0)

# Package igraph

JRES 2015 - Montpellier 8/18


> source (" Pretty -tree.R")
> pretty_tree (table(log[,c("ip","op ")]) , num_clusters = 5, dist_method =" bin ")

Figure 2 - Clustering par arbre de décision et igraph

4.3 Analyse temporelle

Il faut ensuite prendre en compte le second paramètre évident mais important d’un fichier de log : le temps.
La maîtrise statistique des procédés (MSP) (Statistical Process Control ou SPC en anglais) est une technique
statistique du contrôle des processus issue du domaine de la qualité. R propose un package "qcc" qui donne
accès à la plupart des outils utiles à ce type d’analyse. Les courbes de distribution sont particulièrement
intéressantes dans l’analyse de logs. Elles permettent d’améliorer la visualisation de la distribution de don-
nées en y ajoutant des limites de contrôles calculables par diverse méthodes, de l’écart type à la définition
manuelle.

Figure 3 - Courbe de distribution SPC

Les points rouges de la figure 3 indiquent les valeurs de timeout hors des limites moyennes (ULC,LCL) cal-
culées pour toutes les IPs. Une valeur extrême aurait visuellement masquée deux autres valeurs à examiner.

JRES 2015 - Montpellier 9/18


> library (qcc)

> res <- qcc(log[,list(ip , duration )], type =" xbar ")

# indices des valeurs hors limites


> view <- res$violations$beyond . limits

# affichage des IPs hors limites


> log[view ,] $ip
[1] 192.168.7.8 192.168.6.45 192.168.223.67

En réalité, les courbes de distribution traitent les séquences d’évènements et non des durées. R permet
d’effectuer des analyses fréquentielles à partir des données temporelles du fichier de logs. On peut par
exemple étudier un fichier de log de connexions IMAP et détecter qu’un grand nombre de requêtes IMAP
provient d’un client configuré avec un temps très court et non d’une tentative de deny de service. Sur le
graphique ci-dessous (figure 4) on observe un pic à 31,6 sec pour 14000 requêtes imap en une semaine.
L’utilisateur a sans doute configuré une relève automatique à 30 secondes.

Figure 4 - Périodes des requêtes IMAP d’un utilisateur

# extrait de logs de connexions pour login1


> extrait <- droplevels ( extrait ) # nettoyage des valeurs nulles
> summary ( extrait )
V2 V3 V4
imap :26293 login1 :26305 192.168.13.137 :21528
smtp: 12 192.168.142.224: 1427
192.168.15.21 : 962
192.168.139.90 : 664
192.168.144.193: 473
192.168.22.156 : 452
(Other) : 799
# conversion de la chaine de char V1 en temps posix
> extrait$time <- as. POSIXct ( strptime (extrait$V1 ,"%Y-%m-%dT%H:%M:%S +02:00"))

# calcul des durées , sans boucle sé quentielle

JRES 2015 - Montpellier 10/18


> extrait$diff <- c(0, diff( extrait$time ))

# sé lection pour imap


> f <- extrait [diff > 3 & diff <100 & V2 == "imap",list(time ,diff )]

# calcul de période
> d <- density (as. numeric ( f$diff ))

# extraction du maximum
> m <- which.max(d$y)

# graphique
> plot(d)
> abline (v=d$x[m], col = "red", lty = " dotted ", lwd =2)
> text(d$x[m]-2.5,0, round(d$x[m],1), col =" red",cex =1.5)

De la même façon, on peut étudier une journée de tentatives d’attaques par force brute sur des identifi-
ants SSH. La fréquence des tentatives est une caractéristique intéressante des machines attaquantes. Les
graphiques ci-dessous présentent la densité de requêtes des machines les plus actives sur une courte et une
longue durée (figure 5). Si les attaques sur des courtes périodes sont facilement limitées avec des outils
comme fail2ban ou de simples règles iptables, on peut également analyser ces attaques sur une longue
période.

Figure 5 - Périodes des attaques en force brute sur SSH

4.4 Géolocalisation

Un autre exemple d’étude peut être menée sur un fichier centralisant tous les logs de connexions sur une
longue période. Ce fichier contient en moyenne 2 millions de lignes avec l’heure précise, l’identifiant util-
isateur, l’IP source et le service accédé.

JRES 2015 - Montpellier 11/18


Il est de nos jours possible de géolocaliser les adresses IP à partir de bases de données tenues à jours
par diverses sociétés. La plus connue est la base GeoIP de Maxmind. Le package "iptools" 6 de R permet
de manipuler les adresses IP en obtenant le numéro d’autonomous system, de calculer des masques, les
résolutions DNS mais il permet également d’accéder aux informations de géolocalisation comme le pays,
la ville ou encore la latitude et longitude. Maxmind annonce une moyenne de 30% d’erreur pour la France.
Des comptages d’utilisateurs par pays peuvent alors être rapidement calculés et visualisés sur une carte
(figure 6).

Figure 6 - Localisation des utilisateurs

Le paquet "sp" de R permet de manipuler les données géographiques. On peut alors calculer les distances en-
tre IP successives (si la localisation existe). En utilisant les techniques de calcul de périodes, vues précédem-
ment, on peut alors calculer des vitesses de déplacement (figure 7).

Figure 7 - Géolocalisation : usage «normal» lors d’une conférence en Roumanie

6. Ce paquet étant en cours de refactoring, vous pouvez actuellement utiliser mon fork https://github.com/yvesago/iptools

JRES 2015 - Montpellier 12/18


4.5 Performances

Ces calculs peuvent être très longs lorsqu’ils sont appliqués à un très gros volume de données. R permet as-
sez facilement de les paralléliser. L’exemple suivant illustre l’utilisation des packages "foreach" et "doMC".
Le temps de calcul diminue de 3 à 2h en passant d’un calcul sur un processeur mono-coeur (avec un pro-
cesseur d’il y a 4 ans) à un calcul parallélisé sur les 2 coeurs. R permet également de lancer les calculs
parallélisables sur un cluster MPI, OpenMP ou encore Hadoop. 7

> library ( foreach )


> library (doMC)

> registerDoMC (2) # 2 processeurs ,


# %dopar% retourne une liste
> res <- foreach (login = levels ( log$V3 )) %dopar% {
c(login , 0, diff(log[V3== login]$time )) }

> for (a in res) {log[ V3==a[1], diff := a[2: length (a)] ]}

4.6 Exploitation des résultats et «outliers»

La prise en compte de la vitesse de déplacement, du nombre d’utilisateurs par IP ou réseau permet de faire
apparaître les usages de VPN ou de proxy.
Ces premiers résultats ne sont généralement pas utilisables en l’état. Nous avons vu que des techniques
comme le contrôle de processus dépendent de la moyenne ou l’écart type des valeurs. Des valeurs excep-
tionnelles provoquent des biais sur les seuils de détection. De la même façon, l’absence des informations
de géolocalisation ou l’usage de proxy, VPN, produiront des calculs erronés de distances et de vitesses. Il
faut alors choisir comment traiter ces valeurs. Elles peuvent être ignorées ou corrigées.
Lorsque les données aberrantes ont été nettoyées, les recherches d’indicateurs de compromission peuvent
commencer. Ceux-ci apparaîtrons dans des données hors norme : les «outliers». Nous avons vu que la
méthode de contrôle de processus apportait de bon résultats à partir de la moyenne et de l’écart type des
observations traitées. Cependant pour de gros volumes de données, R permet d’utiliser, avec le package
"spoutlier", la récente méthode de détection par sampling de Mahito Sugiyama [3].

5 Conclusion
Cet article permet d’aborder diverses approches de fouilles de données contenues dans des fichiers de logs.
L’objectif est d’apporter une aide à la détection d’évènements anormaux qui pourraient être des indicateurs
de compromission. Nous avons abordé des exemples de fouilles de fichier ldap, de tentatives d’attaque par
force brute ou encore des traces centralisées des connexions des utilisateurs.
Lorsque nous avons abordé les notions élémentaires de statistiques, il apparait que l’approche statistique
impose un certain nombre de précautions d’usage dans le traitement et l’interprétation des résultats. Il
n’y a alors pas de méthode absolue pour conduire une fouille de données. Il faut s’adapter aux types de
données collectées. Un logiciel comme R permet assez simplement de traiter de gros volumes de données
et d’y appliquer de multiples méthodes de traitement. L’approche statistique fait apparaître les éléments qui
7. Parallel Options for R : http://glennklockwood.com/di/R-para.php

JRES 2015 - Montpellier 13/18


doivent être examinés en priorité mais seul l’examen des traces originales permet d’en tirer des conclusions
fiables.
Il apparait que l’usage d’outils et de méthodes statistiques permet d’envisager de créer des modèles de
comportement «normaux». Cependant l’appui d’un statisticien professionnel sera sans doute nécessaire
pour évaluer la validité de ces modèles.
La nouveauté de ces approches dans le domaine du traitement de fichiers de traces bénéficierait certaine-
ment de la mise en place d’une communauté qui pourrait explorer des techniques spécifiques prometteuses,
comme le clustering de données temporelles, et vulgariser des méthodes d’explorations pour améliorer le
traitement à but préventif des fichiers de traces.

Bibliographie
[1] Richard Tomassone Lise Bellanger. Exploration de données et méthodes statistiques. ellipses, 2014.
[2] Vincent Goulet. Introduction à la programmation en R. 2014. https://cran.r-project.org/doc/contrib/
Goulet_introduction_programmation_R.pdf.
[3] Borgwardt K. M. Sugiyama M.. Rapid distance-based outlier detection via sampling. Advances in
Neural Information Processing Systems (NIPS 2013), pages 467–475, 2013. http://papers.nips.cc/
paper/5127-rapid-distance-based-outlier-detection-via-sampling.pdf.

Ressources complémentaires en ligne


– Statistiques pour statophobes. D. Poinsot , 2004. En ligne
– Se procurer et gérer R sur debian : https://cran.r-project.org/bin/linux/debian/
– R pour les statophobes. D. Poinsot , 2005. En ligne
– Aide mémoire R En ligne

JRES 2015 - Montpellier 14/18


Annexe

Exemple complet

Étude d’un fichier auth.log, provenant d’un serveur disposant de protections contre les attaques en force-
brute.

# extraction classique des éléments à é tudier


$ grep ’for invalid user ’ /var/log/auth.log |
awk -F’ ’ ’{print $1" "$2" "$3"," $11 "," $13}’ > auth -ssh.log
# é ventuellement "| sed s/Oct/oct ./" pour obtenir le bon format de date

$ R
> lg <- read.csv ("auth -ssh.log", header = FALSE)
> lg$time <- as. POSIXct ( strptime (lg$V1 ,"%b %d %H:%M:%S"))
> lg$V1 <- NULL # la colonne V1 est maintenant inutile

> library (data.table) # data.table simplifie un peu la syntaxe


> lg <- data.table(lg)

> colnames (lg) <- c(" login ","ip"," time ") # on renomme , c’est plus joli

# Scatterplot
> pairs(lg , lower.panel = panel.smooth , upper.panel = panel.cor ,
diag.panel = panel.hist)

Figure 8 - Scatterplot d’un fichier de auth.log

JRES 2015 - Montpellier 15/18


On observe (figure 8) :
– peu de corrélation : il n’y pas de redondance. Le fichier de log semble cohérent
– un login plus recherché
– 3 IPs plus actives
– des pics d’activité : les 5, 8 et 12 octobre
– la distribution des valeurs ne semble pas indiquer de cluster exploitable
On retrouve ces valeurs dans les tableaux de fréquence :

# tableaux de fré quence triées


# login cherch és :
> sort( table( lg$login ) )
ts3bot ubnt test admin
11 11 18 68
# IPs :
> sort( table(lg$ip) )
193.95.84.205 91.221.41.232 192.162.112.138 136.243.45.200 91.121.155.219
5 5 23 33 70
202.104.68.30 85.214.253.70
77 132

# tableau de fré quence découpé par jour


> table( cut(lg$time , breaks =" days ") )
2015 -10 -04 2015 -10 -05 2015 -10 -06 2015 -10 -07 2015 -10 -08 2015 -10 -09 2015 -10 -10
47 127 22 52 80 40 34
2015 -10 -11 2015 -10 -12 2015 -10 -13 2015 -10 -14 2015 -10 -15
52 64 31 17 2

Étude de cluster des IPs par login

pretty_tree (table(lg$ip , lg$login ), num_clusters = 10, dist_method =" bin ")

Figure 9 - Cluster non significatif

JRES 2015 - Montpellier 16/18


Ici (figure 9) le résultat ne semble pas significatif : les 10 groupes sont relativement homogènes. Il ne semble
pas utile de poursuivre dans cette recherche.

Étude des fréquences d’accès aux logins

Peut-être qu’une tentative de brute-force distribuée à eu lieu :

> for (l in levels ( lg$login )) {lg[login ==l,diff := c(0, diff(time ))]}

# sé lection des 18 comptes les plus accédés


> t <- names(head(sort(table( lg$login ), decreasing = T) ,18))

# grille d’ affichage
> par( mfrow=c(6 ,3))

# traitement
> for ( l in t) {
ts <- lg[login ==l]
f <- ts[,list(time ,diff )]
d <- density (as. numeric ( f$diff ))
m <- which.max(d$y)
plot(d,main=l)
abline (v=d$x[m], col = "red", lty = " dotted ", lwd =2)
text(d$x[m],0, round(d$x[m],1), col =" red",cex =1.5)
}

Ici (figure 10) les pics de périodes sont à explorer. Les périodes observées étant élevées le risque de com-
promission est faible. Il s’avère que pour cet exemple il s’agit de tentatives de nouvelles machines.

Étude de géolocalisation 8

> library ( iptools )


> maxmindinit ()

> L <- c(" country .code "," region .name "," city "," longitude "," latitude ")

> lg[,c("cn"," region "," city "," long "," lat ") := geoip(ip)[L] ]

> lg[,c(" asn "," asnorg ") := asnip(ip)[c(" asn "," org ")]]

> table(lg$cn)

AR BR CN CO DE DO FR GB HK ID IL IN IT JP KR KZ MX MY NL
2 5 158 8 170 1 70 2 2 3 3 5 2 5 9 3 6 1 3
PL PT RO RS RU TH TN TW UA UG US VN
1 2 3 2 16 6 5 2 28 2 40 3

L’étude de géolicalisation n’est pas forcément utile. Les machines qui tentent ces attaques en force-brute
sont généralement des serveurs déjà compromis.

8. Le paquet iptools étant en cours de refactoring, vous pouvez actuellement utiliser mon fork https://github.com/yvesago/iptools

JRES 2015 - Montpellier 17/18


Figure 10 - Fréquences des tentatives d’accès

JRES 2015 - Montpellier 18/18

Vous aimerez peut-être aussi