Académique Documents
Professionnel Documents
Culture Documents
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.
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.
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.
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
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.
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.
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.
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.
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
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
# 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
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.
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.
> res <- qcc(log[,list(ip , duration )], type =" xbar ")
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.
# 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.
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é.
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).
6. Ce paquet étant en cours de refactoring, vous pouvez actuellement utiliser mon fork https://github.com/yvesago/iptools
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
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
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.
Exemple complet
Étude d’un fichier auth.log, provenant d’un serveur disposant de protections contre les attaques en force-
brute.
$ 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
> 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)
# 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
> 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