Aujourd’hui de nombreux particuliers et entreprises déploient sur leur réseau privé différents objets interconnectés entre eux et à Internet. Ces composants qui disposent de peu de ressources et communiquant pour la plupart en utilisant des technologies sans fil forment un réseau, communément appelé réseau IoT.
Cependant, ces réseaux utilisent des objets hétérogènes qui communiquent au travers de différents protocoles IoT, comme par exemple Bluetooth Low Energy (BLE), Zigbee ou 6LoWPAN. Cette hétérogénéité les rend complexes à contrôler, administrer et à analyser.
IoTMap est une plateforme facilitant la compréhension et l’analyse de réseaux IoT hétérogènes avec une vision sécurité. Il peut être utilisé, aussi bien dans une évaluation de sécurité du réseau avec un point de vue offensif (test d’intrusion par exemple), que défensif (détection ou prévention d’attaques).
IoTMap
IoTMap permet de comprendre et de cartographier les réseaux IoT afin de mieux les administrer et les sécuriser. Pour cela, le framework est composé de plusieurs parties, illustrées dans la figure ci-dessous.
Ce framework est capable d’intercepter le trafic du réseau observé, de le capturer et de le sauvegarder dans un format de type PCAP. A partir des captures enregistrées, IoTMap analyse le trafic afin de détecter certains comportements définis par des patterns, pouvant représenter l’orientation du flux de données ainsi que les rôles des objets du réseau. Enfin, IoTMap propose une visualisation du réseau observé par des graphes.
Présentation générale
La figure ci-dessus illustre l’architecture générale d’IoTMap, décomposée en trois parties principales : l’écoute, l’analyse et la visualisation.
La partie écoute, représentée à gauche sur la figure, s’occupe de l’interception des communications, la capture du trafic et la conversion des paquets, spécifiques au format du protocole observé dans un format homogène.
La partie analyse prend en charge la modélisation des différents graphes. Le processus de modélisation est itératif, où la création d’un graphe nécessite les informations obtenues et générées par le graphe précédent. IoTMap utilise le graphe courant ainsi que les patterns associés afin de construire le graphe suivant. Chaque graphe généré est stocké en base de données, en suivant le formalisme proposé par le langage Neo4j.
La dernière partie de l’architecture d’IoTMap, la visualisation, permet à l’utilisateur d’avoir une représentation graphique du réseau observé. L’interface est accessible depuis un navigateur Web, en accédant directement au service exposé par Neo4J. La partie visualisation offre plusieurs possibilités. Une liste de requêtes préconfigurées permet l’affichage de tous les graphes générés lors de la modélisation ou l’accès à différents éléments détectés par les patterns. Il est également possible d’effectuer des requêtes au format Cypher pour interroger la base de données, afin d’obtenir des graphes ou toutes autres données plus spécifiques dans le but d’effectuer une analyse plus approfondie.
Présentation des modules d'IoTMap
Pour assurer toutes les fonctionnalités, nous avons composé IoTMap en quatre modules indépendants :
- Paquet Générique : Module en charge de la conversion des paquets au format spécifique d’un protocole vers un format homogène, définit dans IoTMap. L’objectif de ce module est d’uniformiser la modélisation peu importe le protocole IoT étudié ;
- Interception : Module en charge des capacités d’interception d’IoTMap. Il organise les différents matériels et logiciels utilisés pour intercepter les communications des protocoles IoT ;
- Modélisation : Module en charge de la création des graphes de modélisation. Il analyse les communications observées, utilisent une librairie de patterns pour détecter des comportements spécifiques afin de produire une modélisation du réseau observé ;
- Base de données : Module en charge du stockage des données obtenues. Il repose principalement sur l’utilisation du composant neo4j pour stocker les données dans un format spécifique.
Bien que ces modules soient indépendants, de nombreuses relations sont entre les modules assurent la bonne réalisation des différentes actions du framework. Par exemple, le module Interception doit pouvoir utiliser plusieurs fonctions du module Paquet générique, pour convertir les paquets spécifiques d’un protocole vers le format générique. De plus, le module Interception nécessite également l’accès aux fonctions du module Base de données, pour stocker les paquets capturés dans la base de données Neo4J.
Interception des communications
IoTMap dispose de deux méthodes pour ingérer les communications des réseaux IoT. La première méthode, dite offline, consiste à importer directement des traces de captures au format PCAP. La seconde, dite live, consiste à attacher plusieurs sondes de captures au dispositif qui utilise IoTMap afin de procéder à la capture des communications.
Quel que soit la méthode choisie, les outils utilisés pour effectuer l’interception des communications restent identiques en fonction du protocole ciblé. Nous avons opté pour une intégration des outils existants (Killerbee, Sensniff et Btlejack) dans IoTMap afin d’utiliser des outils éprouvés en fonction du protocole. Cette vision a pour objectif de simplifier l’usage de ces outils et d’unir dans un même framework plusieurs outils pour assister l’utilisateur dans l’amélioration de la sécurité de son réseau IoT.
Interception : mode live
Dans ce mode, la partie interception est contrôlée par IoTMap. De cette façon, les paquets interceptés sont directement importés dans la base de données Neo4J, après être convertis au format homogène d’IoTMap, de manière totalement transparente pour l’utilisateur. Il est également possible, par différentes options, de sauvegarder le résultat de l’interception dans un fichier de sortie au format PCAP.
Pour utiliser ce mode, il faut entrer dans le module sniffing d’IoTMap, définir les différents sniffers à utiliser à l’aide de la fonction addSniffer et lancer l’interception.
IoTMap sniffing > addSniffer -h
Add a sniffer to IoTMap
Usage: addSnifer (--identifier <id>) [--name <name>] (--protocol <protocol>) (--device <device>)... (--channel <channel> | --connreq <connreq>) [--packetNb <packetNb>] [-h]
Options:
-h, --help print this help menu
-p, --protocol <protocol> Define the type of sniffer
-n, --name <name> Name of the sniffer
-i, --identifier <id> Unique identifier to identify the sniffer
-d, --device <device> Device to use to process the sniffing. Several devices can be setup
-c, --channel <channel> Channel on which the sniffer will listen. This option is protocol-specific
-a, --connreq <connreq> BLE specific option - Device address to focus on
-t, --packetNb <packetNb> Number of packets to listen
Remarks:
In the case of BLE, the channel corresponds to the access address.
Examples:
addSniffer --identifier 1 --protocol os4i --device /dev/ttyACM0 --channel 25
addSniffer --identifier 1 --protocol zigbee --device 1:5 --channel 25 -t 1500
addSniffer --identifier 1 --protocol btle --device /dev/ttyACM0 --device /dev/ttyACM1 --channel 0xbb94dbbd
addSniffer --identifier 1 --protocol btle --device /dev/ttyACM0 --device /dev/ttyACM1 --connreq E0:14:9E:14:11:72
IoTMap intègre plusieurs commandes qui permettent d’interagir avec les sniffers. Il faut dans un premier temps ajouter les différents sniffers à disposition. En fonction du protocole à intercepter, le logiciel et le matériel diffèrent. Par exemple, dans le cas d’un réseau Zigbee, le logiciel utilisé est KillerBee[^killerbee]. Il faut donc ajuster les options d’IoTMap pour assurer celles dédiées à chaque logiciel utilisé. Ainsi, pour Killerbee, il faut définir le canal (-c 25) et indiquer l’identifiant du matériel (-d 3:6).
IoTMap sniffing > addSniffer --identifier 1 --protocol zigbee --device 3:6 --channel 25 -t 1500
Warning: You are using pyUSB 1.x, support is in beta.
[i] Sniffer saved !
Avant de démarrer l’interception des communications, il est possible de lister les différents sniffers précédemment ajoutés afin de vérifier si le dispositif est en cours d’exécution ou non.
IoTMap sniffing > listSniffers
List of available sniffers:
Idenfifier Name device(s) Protocol Is_alive
---------------------------------------------------
1 zigbee 3:6 zigbee False
Lorsque tous les sniffers pour tous les protocoles sont définis, la commande run
permet de démarrer l’interception et la commande stopSniffer
l’arrête.
Interception : mode offline
Dans ce mode, l’interception des communications est effectuée à côté d’IoTMap. Il faut donc que l’utilisateur manipule les outils d’interception directement et récupère les fichiers de sortie. Il convient par la suite de les importer dans IoTMap. Pour effectuer cette opération, il faut se rendre dans le module database d’IoTMap.
Plusieurs commandes sont disponibles dans ce module. Pour ajouter des données dans la base de données, il est possible d’utiliser la fonction importDB
pour importer une base de données directement. La fonction importPCAPS
permet également d’importer des données mais à partir des fichiers de captures des communications. Pour chaque commande, un menu d’aide est disponible et accessible en utilisant l’option -h
.
IoTMap database > importPcaps -h
Import pcap files into the database
Usage: importPcaps (<protocol> <pcap>)... [--output <filename>] [--thread <nbThread>] [--nodesFile <nodesFile>]
Options:
-h, --help Print this message.
-o, --output <filename> Output file to store the result.
-t, --thread <nbThread> Thread number to use [default: 1].
-n, --nodesFile <nodesFile> File that contains a list of nodes used in communications.
Arguments:
protocol Name of the IoT protocol.
pcap Pcap file from the specific protocol defined in the previous arg.
Examples:
import_pcap zigbee file1.pcap zigbee file2.pcap os4i file3.pcap --thread 2 -o zigbee-os4i.csv
import_pcap btle file1.pcap os4i file3.pcap -t 2 -o btle-os4i.csv
import_pcap os4i file.pcap --thread 3 --debug --output os4i.csv
IoTMap database >
Ainsi, pour importer des fichiers de capture, il faut utiliser la fonction importPCAPS
. Il est également possible d'importer plusieurs fichiers de captures simultanément et de protocoles différents si nécessaire. Peu importe la méthode choisie pour importer des données, ces dernières seront par la suite accessibles et manipulables depuis le module database
.
Modélisation
Une fois que le trafic intercepté est importé dans IoTMap, il est possible de le modéliser sous forme de plusieurs graphes. Cela permet d’obtenir une visualisation du réseau et, en fonction des patterns exécutés, d’identifier plusieurs interactions ou comportements.
Cette modélisation offre plusieurs avantages, que ce soit pour de l’offensif ou du défensif, comme par exemple mettre en avant les objets qui interagissent indirectement afin de cibler les objets à attaquer. Cette même information peut également mettre en avant des communications entre objets qui ne devraient pas avoir lieu, laissant deviner une potentielle compromission.
Pour effectuer la modélisation, IoTMap génère plusieurs graphes. Ils sont créés après l’exécution de multiples patterns définis dans IoTMap. Ces patterns effectuent une analyse sur les graphes afin de détecter différents comportements permettant la création d'autres graphes.
Génération des graphes
La modélisation produite par IoTMap est une représentation du réseau en plusieurs graphes, où chaque graphe apporte son propre niveau de connaissances et d’informations. Comme le montre la figure ci-dessous, la génération des graphes est itérative. De plus, chaque graphe produit par la modélisation peut être inspecté et visualiser sur l’interface web offerte par Neo4J.
Comme le montre la figure, la modélisation commence avec l’analyse des captures de communications (PCAPs dans la figure). Cette analyse repose sur l’utilisation de pattern (identifié par FDL) pour produire le premier graphe (GDL dans la figure). De manière itérative et similaire, le second graphe est produit à partir d’une analyse du graphe GDL à l’aide des patterns FNWK et ainsi de suite jusqu’à produire l’ensemble des graphes. Chaque itération de la modélisation permet à l’utilisateur d’obtenir un niveau d’information spécifique et différent. Par exemple, le graphe GDL expose les communications point à point entre les objets et le graphe GNWK expose les communications finales ou end-to-end.
Toutes les fonctionnalités présentées dans la méthodologie sont incluses dans le module modelling
d’IoTMap. Comme expliqué plus haut, la modélisation débute avec le premier graphe, le graphe de liaison (GDL). Après avoir sélectionné le module modelling
, il suffit d'exécuter la commande suivante :
IoTMap modelling > dlGraph
Sans fournir d’options à cette commande, IoTMap va utiliser les données stockées dans la base de données pour générer le graphe correspondant. Cette stratégie vaut d’ailleurs pour toutes les commandes. Cependant, pour générer l’ensemble des graphes, il faut effectuer toutes les commandes de manière itérative.
IoTMap modelling > nwkGraph
IoTMap modelling > transGraph
IoTMap modelling > appGraph
Si nous disposons déjà de traces formatées au format homogène d’IoTMap, il est possible de les utiliser avec n’importe quel graphe. Ainsi, il est possible de générer l’ensemble des graphes en utilisant la commande suivante
IoTMap modelling > appGraph -f tests/test-all-with-protocol.csv
Pour observer la modélisation produite, il faut se rendre depuis son navigateur sur l’URL http://localhost:7474.
Plusieurs éléments sont disponibles. Sur le panneau gauche de l’application se trouvent les étiquettes des différents arcs et graphes de la modélisation. Les graphes générés peuvent être observés et analysés dans la partie droite de l’application. Enfin, une barre de texte est disponible pour effectuer des requêtes au langage Cypher afin d’interagir directement avec la base de données.
Création de patterns
La génération des graphes par IoTMap s’appuie sur la détection d’éléments dans les graphes précédents en utilisant des patterns, précédemment définis et ajoutés dans IoTMap.
Ces patterns sont des fonctions qui vont analyser et détecter certains comportements dans les captures de communications ou les graphes de la modélisation. Le principal langage de programmation utilisé pour décrire ces fonctions est Cypher. Cependant, si le pattern est trop complexe, nous utilisons les deux langages de programmation simultanément : Cypher pour interagir avec la base de données Neo4J et Python pour effectuer des calculs plus complexes.
Les patterns utilisés par IoTMap doivent permettre à l’utilisateur d’obtenir de l’information sur le fonctionnement du réseau dans le cas d’un pentest. Ils peuvent également servir de mécanismes permettant de vérifier que le déploiement effectué est conforme à ce qui est souhaité.
Ainsi, nous pouvons écrire des patterns qui peuvent être utilisés aussi bien pour de l’offensif que pour du défensif. IoTMap vient avec plusieurs patterns par défaut qui permettent de construire les premiers graphes. Nous proposons également quelques patterns applicatifs qui permettent entre autres de détecter des interactions indirectes entre objets.
Selon l’usage d’IoTMap, il convient d’ajouter ses propres patterns pour effectuer la détection et produire une modélisation plus spécifique et avancée de son réseau IoT. La création d’un nouveau pattern peut être faite en complétant le squelette de code suivant
@classmethod
def nom_pattern(cls, tx,):
result = tx.run("cypher_request")
#Code python si nécessaire
En fonction de la complexité du pattern, il est possible d’utiliser uniquement des requêtes Cypher. Par exemple dans IoTMap, la création ou la suppression des noeuds reposent uniquement sur une requête Cypher.
@classmethod
def delete_nodes(cls, tx, label):
tx.run("""
MATCH (n: Node)
where n.label >= $label
optional match (n)-[r]-()
delete r, n""", label=label
)
Dans le cas de patterns trop complexes, nécessitant des calculs ou des opérations plus avancées et non réalisables en utilisant des requêtes Cypher, il est possible de coupler les résultats obtenus par les requêtes Cypher et le langage Python. C’est le cas, par exemple, du pattern qui définit les interactions dans le réseau.
@classmethod
def interact(cs, tx, delta):
delta = delta
results = tx.run("""
match p=(n:Node{label: 4})-[:TRANSEdge*1..]->(c: Node{label: 4})-[:TRANSEdge*1..]->(m:Node{label: 4})
where 'source' in n.role and 'sink' in m.role and n <> m and 'controller' in c.role
return p
""")
for result in results:
nbRel = len(result["p"].relationships)
rel = result["p"].relationships
count = 1
for i in range(1, nbRel):
TX1 = rel[i - 1]['timestamp']
TX2 = rel[i]['timestamp']
for t2, t1 in ((tx2, tx1) for tx2 in TX2 for tx1 in TX1):
if t2 > t1 and t2 - t1 < delta:
count += 1
break
# Reste du pattern
Les patterns sont ensuite ajoutés aux autres patterns disponibles d’IoTMap et peuvent être utilisés avec la commande suivante :
IoTMap modelling > appGraph -p nom_pattern
Conclusion
IoTMap est un framework qui permet de modéliser les réseaux IoT en mettant en évidence des comportements définis par des patterns. IoTMap a pour objectif de faciliter, d’aider à la réalisation d’analyse de sécurité des réseaux IoT. Ce framework peut être utilisée par un "attaquant" pour lui offrir une cartographie du réseau à auditer. Il peut également être utilisé par une équipe de défense du réseau IoT pour analyser et assurer le bon déploiement des objets.
IoTMap permet d’analyser des réseaux IoT de différents protocoles, simultanément ou non. Sa conception modulaire facilite également l’ajout de nouveaux patterns pour affiner la modélisation en fonction des contextes, mais également de nouveaux protocoles pour étendre les fonctionnalités d’IoTMap au plus de réseaux possibles.
Actuellement, IoTMap supporte trois protocoles IoT différents : ZigBee, BLE et 6lowpan. De plus, il est capable de produire une modélisation du réseau même lorsque les communications observées sont chiffrées. IoTMap est accessible en Open Source sur Github.
À propos : Le blog d'AlgoSecure est un espace sur lequel notre équipe toute entière peut s'exprimer. Notre personnel marketing et commercial vous donne des informations sur la vie et l'évolution de notre société spécialisée en sécurité sur Lyon. Nos consultants techniques, entre deux tests d'intrusion ou analyses de risque, vous donnent leur avis ainsi que des détails techniques sur l'exploitation d'une faille de sécurité informatique. Ils vous expliqueront également comment sécuriser votre système d'informations ou vos usages informatiques particuliers, avec autant de méthodologie et de pédagogie que possible. Vous souhaitez retrouver sur ce blog des informations spécifiques sur certains sujets techniques ? N'hésitez pas à nous en faire part via notre formulaire de contact, nous lirons vos idées avec attention. Laissez-vous guider par nos rédacteurs : Alexandre, Amine, Antonin, Arnaud, Benjamin, Damien, Enzo, Eugénie, Fabien, Françoise, Gilles, Jean-Charles, Jean-Philippe, Jonathan, Joël, Joëlie, Julien, Jéromine, Ludovic, Lyse, Nancy, Natacha, Nicolas, Pierre, PierreG, Sébastien, Tristan, Yann, et bonne visite !