Passer du 2D à la profondeur
Un log, c’est du 2D, un simple bout de texte parfois un peu enrichi. Alors que nous passons le plus clair de notre temps à lire des affreuses lignes de logs dans nos terminaux, nos SIEM et autres outils, les attaquants progressent toujours et de plus en plus vite… Pour nous aider dans cette chasse aux vilains, voici un petit billet de blog sur la représentation en graphe de nos données.
Attention, il s’agit d’un essai pour conduire à de nouvelles idées et manières de travailler. C’est le premier article d’une série où je présenterai des exemples des concepts posés ici. J’espère que cet article vous plaira !

Résultat obtenu à partir de logs Zeek
Le graphe pour l’attaquant
Alors que nous, défenseurs, réfléchissons en surface d’attaque, en topologie réseau et en vulnérabilités, un attaquant pense graphe (même s’il ne le sait pas).
Pour lui, une étape pourrait peut-être le mener à une deuxième ou à une troisième, jusqu’à l’atteinte de son objectif final.
Prenons un groupe qui donnerait dans le cybercrime et qui en serait au tout début de son attaque. Chaque noeud représente une action qui pourrait être réalisée par GM (soit Grand Méchant).
C’est quoi un graphe d’abord
Un graphe, c’est une structure de données composée de noeuds (aussi appelés vertices) et d’arêtes (edges) qui les relient. C’est tout. La définition est simple, mais ses applications sont infinies.
Concrètement : imaginez une carte de métro. Chaque station est un noeud, chaque ligne qui les connecte est une arête. Vous avez un graphe.
Dans notre contexte cyber, un noeud peut représenter à peu près n’importe quoi : une machine, un utilisateur, une adresse IP, un ticket Kerberos, un processus… Et une arête représente une relation entre deux de ces éléments : une connexion réseau, une authentification, une exécution de processus, un accès fichier.
Ce qui rend les graphes particulièrement puissants, c’est qu’ils permettent de raisonner sur les chemins. Pas seulement sur ce qu’est un élément, mais sur comment on peut passer de l’un à l’autre ; et c’est précisément ce dont on a besoin pour modéliser le déplacement d’un attaquant dans un SI.
Il existe plusieurs types de graphes, mais ceux qui vont nous intéresser le plus sont les graphes orientés et pondérés. Chaque arête a un sens (une flèche) et porte un poids (une valeur).
Voyons comment appliquer cette structure à une attaque.
Exemple d’un phishing
Les noeuds en rouge représentent les étapes déjà réalisées par l’attaquant.

Ci-dessus, GM (Grand Méchant) vient de compromettre le poste de Louise-Marie, comptable dans une entreprise de développement logiciel.
Actuellement, il n’a qu’une vague idée des étapes qui pourront le mener jusqu’au déploiement du ransomware. Probablement que certaines de ces étapes échoueront, et que d’autres lui dévoileront d’autres possibilités au fur et à mesure.
Si GM décide d’avancer un peu en réalisant un scan réseau de son entourage, on pourrait imaginer la progression suivante :

Ainsi, en ayant effectué un scan réseau, GM s’ouvre de nouvelles possibilités qui le mèneront plus ou moins rapidement au déploiement de son ransomware.
L’exemple de BloodHound
BloodHound est l’exemple parfait de la pensée graphe appliquée à l’attaque. Cet outil est conçu pour trouver les chemins les plus courts dans un environnement Microsoft jusqu’à un objectif.

Représentation d’un graphe BloodHound
La pensée en graphe du défenseur
Pour un défenseur, être capable de modéliser en graphe les possibilités de progression d’un attaquant dans son réseau est intéressant à plus d’un titre :
- identifier les points sensibles à renforcer ;
- mettre en place du monitoring aux emplacements stratégiques ;
- comprendre et contenir l’attaquant lors d’une réponse à incident.
Imaginons un graphe capable de représenter toutes les actions redoutées dans notre SI et leurs transitions :

Dans le graphe imaginé ci-dessus, on a pu identifier deux goulots d’étranglement en vert. Ceux-ci seront des points d’attention particuliers dans notre SI où nous pourrons redoubler de vigilance sur le monitoring et la sécurité.
Application à l’investigation numérique
En DFIR, il s’agit souvent de partir d’un incident cyber et de pivoter à travers toutes les données que nous avons à notre disposition pour trouver où est-ce que l’attaquant a pu aller et ce qu’il a pu faire.
Le pivot en analyse est ce qui distingue un bon analyste d’un moyen : sa capacité à identifier un marquant, et à changer son point de vue d’analyste pour reprendre ce nouveau marquant en point d’entrée.
Exemple :

Ci-dessus, durant son investigation, l’analyste identifie un nouveau marquant : le JA3S correspondant au serveur malveillant. En pivotant sur ce nouveau marquant, il pourrait identifier de nouveaux serveurs malveillants encore inconnus.
Dans un SIEM classique
Dans ELK, ça donnerait quelque chose comme ça :
Étape 1 - on fait notre recherche sur le client compromis :
FROM logs-zeek.ssl-*
| WHERE destination.ip == "185.234.X.X"
| KEEP source.ip, destination.ip, tls.server.ja3s, @timestamp
| SORT @timestamp DESC
On récupère le JA3S : d41d8cd98f00b204e9800998ecf8427e. On pivote.
Étape 2 - on cherche toutes les IPs qui partagent ce fingerprint TLS, hors de notre C2 déjà connu :
FROM logs-zeek.ssl-*
| WHERE tls.server.ja3s == "d41d8cd98f00b204e9800998ecf8427e"
AND destination.ip != "185.234.X.X"
| STATS connexions = COUNT(*),
premiers_contacts = MIN(@timestamp),
sources = VALUES(source.ip)
BY destination.ip
| SORT connexions DESC
Dans un outil graphe
Et voilà à quoi ressemblerait un pivot dans un outil graphe :

Ici, un pivot sur le JA3 465396b6226909fc5c37f2a3d0e6dcf4 serait juste réalisé par un clic droit par l’analyste. La coloration de noeuds identifiés comme suspects pourrait également se faire avec un autre clic droit.
Vers une analyse multidimensionnelle
Si nous étions capables de faire rentrer toutes les données dans une base de données graphe, on pourrait faciliter grandement l’analyse de bien des manières.
Faciliter le pivot entre la donnée CTI et d’investigation
Il est souvent difficile de faire le lien entre ses données d’investigation et de la donnée OSINT. Aujourd’hui, un analyste qui tombe sur une IP suspecte va ouvrir VirusTotal dans un onglet, Shodan dans un autre, et croiser manuellement avec ses logs dans un troisième. C’est laborieux et ça casse le fil de l’investigation.
Si tout était représenté dans un même graphe, avec pour noeuds les observables communs : IP, domaine, hash, JA3S…, le pivot entre donnée CTI et donnée d’investigation deviendrait naturel. On verrait immédiatement qu’une IP identifiée dans nos logs est également connue dans un rapport de threat intelligence, et on pourrait remonter le fil dans les deux directions sans changer d’outil.
Détection d’anomalies grâce au machine learning
Les algorithmes de machine learning classiques travaillent sur des vecteurs de features : des tableaux de valeurs. Mais certains patterns suspects n’ont pas de sens dans un tableau, ils n’ont de sens que dans une structure relationnelle.
Un compte qui rebondit de machine en machine en dehors de ses habitudes, un hôte qui commence à scanner son voisinage, un processus qui initie des connexions que seul un autre binaire faisait d’habitude… Ces comportements sont invisibles dans une table de logs, mais ils dessinent des formes reconnaissables dans un graphe.
Des algorithmes adaptés aux structures de graphe, les GNN (Graph Neural Networks), permettraient de détecter automatiquement ces patterns sans avoir à les écrire manuellement sous forme de règles. On passerait d’une détection par liste noire à une détection par anomalie structurelle.
Une corrélation système-réseau
Dans les exemples précédents, nous avons surtout parlé de donnée réseau. Mais une connexion réseau sans contexte système, c’est une moitié d’information.
Imaginons qu’on vienne enrichir notre graphe avec les Event ID 4624 (authentifications Windows) et les Event ID 3 Sysmon (connexions réseau initiées par un processus). On serait alors capables de répondre à des questions autrement impossibles : quel processus, sur quelle machine, a initié cette connexion vers ce C2 ? Ce compte s’est-il authentifié juste avant ce mouvement latéral ? La corrélation qui prenait des heures dans un SIEM deviendrait une traversée de graphe.
Et ce n’est qu’un début ; les usages qu’il reste à imaginer sont probablement les plus intéressants.
En pratique
Afin d’explorer le sujet de la transformation de données réseau en graphe, je travaille actuellement sur un projet nommé JACG (Just a Cyber Graph) : https://github.com/theophane-droid/jacg, basé sur Neo4j, dont vous avez eu des extraits au long de l’article.
Je développerai plus sur l’implémentation et l’utilisation pratique de cet outil dans les prochains articles.
Conclusion
Un des problèmes de cette approche est la difficulté pour traiter en amont les données et les faire rentrer dans un graphe. Rendez-vous dans la prochaine partie pour découvrir comment transformer nos logs Zeek en graphe !
