Le Wifi, comment ça marche 2/2
Dans la première partie, on va vu comment fonctionnait les probes, et l’authentification, mais il reste encore deux ou trois trucs à comprendre avant de pouvoir surfer tranquillement sur google.
LET’S GO !
Association
Admettons que tout ce soit bien passé jusqu’à maintenant. Il reste encore une étape obligatoire afin que mon laptop puisse enfin se connecter au reste du réseau, c’est l’association. Jusqu’à maintenant, nous avions découvert les AP via les probes, puis nous avons validé qu’on pouvait s’y connecter avec l’authentification. Du coup, il ne rest plus qu’à finaliser la connexion, via un échange de requête/réponse du type Association.
La première question qui m’est venue en tête en lisant les docs a été “Pourquoi faire ?!”. Je veux dire, l’AP et la station sont potes maintenant, ils se sont dit des formalités, se sont serrés la pince et tout, donc où est l’intéret ?
Et bien en fait, tout simplement pour échanger des informations supplémentaires. Dans ces infos, on retrouve par exemple le SSID du wifi, le BSS (Basic Service Set), etc. Il sert également à transmettre l’AID (Association ID) qui est l’équivalent d’une prise réseau dans une architecture câblé (une borne, ça ne sera jamais qu’un switch, donc elle a besoin d’une “prise” sur laquelle le client se branchera).
Bon maintenant, vous êtes habitués aux trames, donc on va pas y aller par quatres chemins. Le supplicant envoie le premier message, et l’AP la réponse associée :
Les paramètres importants de la requête d’association envoyée par la station sont :
- Le Frame Control positionné à 0x0000
- Les capabilities, définissant les capacités demandées par l’AP lors du probe response et utilisables par la station. Enfin je crois.
- Le Listen Interval, qui donne à quelle intervalle de temps le supplicant écoutera les frames de type Beacons, si le Power Save Mode est activé
- Une foultitude de paramèters taggués, dépendants d’options diverses et variées
Sur le même principe, la réponse émise par l’AP sont :
- Le Frame Control mis à 0x0001
- Les capabilities, qui valide ce qui a été envoyé par le client.
- Le Status Code, mis à 0x0000 si l’association s’est déroulée correctement et que les capabilities sont correctes
- L’Association ID, qui est bahhhh… un ID quoi ^^
- Et encore une fois plusieurs paramètres optionnels
Je ne détaille pas les différentes capabilities, ni les paramètres taggués, déjà parce que je voulais faire un article, pas réécrire toute la doc, et ensuite parce que ça fait intervenir des notions dont je n’ai pas parlé, et qui ne font pas partie du process de connexion.
Bref, une fois que la réponse a été reçue par la machine, on peut considérer que CA Y EST ! ENFIN, on est connecté au wifi !
WPA et WPA2
Ca y est ? On est connecté ? Vraiment ? Well… Pas tout à fait en fait :D
Et oui, souviens toi lecteur, jusqu’à présent, on se connectait sur des réseaux “Open” ou “Shared Key”. Mais je n’ai pas encore parlé ici de l’authentification via TKIP ou CCMP !
Donc, pour des réseaux hotspot ou WEP, on s’arrête ici.
Par contre, pour les réseaux WPA/WPA2, il reste une étape obligatoire : l’authentification 802.1X (à ne pas confondre avec le 802.11, attention). Bah oui, puisqu’il a fallu rendre le tout un minimum interopérable, on a du rajouter une (dernière) couche après l’association pour ces deux chiffrements.
Concrètement, le 802.1X est une norme, qui utilise le protocole EAP (pour Extensible Authentication Protol). Globalement, un poste (en câblé ou non) voulant accéder au réseau doit pouvoir prouver sa bonne foi. L’équipement directement connecté -un switch sur du câblé ou l’AP pour du wifi- à ce poste bloque tout accès au réseau (il “ferme” le port) tant que l’identité n’est pas validée. Une fois que le poste est validé, il “ouvre” le port afin que la station puisse discuter avec le réseau. Pour prouver son identité, c’est assez libre, on peut utiliser l’adresse MAC, un identifiant AD, ou encore… une clé wifi :)
Comme j’ai déjà expliqué en grande partie cette authentification dans mon article sur KRACK, je ne vais pas m’embéter à tout réécrire ici, et je vous laisse aller le lire :) Attention cependant, je suis resté assez spécifique au 802.1X wifi. Comme c’est une norme de plus en plus utilisée, il y a pas mal de lecture sur les internets pour du 802.1X cablé, donc je vous laisse le loisir de chercher ^^
Le détail du format
Depuis tout à l’heure, j’explique le fonctionnement du 802.11 d’une manière assez statique, c’est à dire que pour chaque type de paquet, j’ai détaillé ce qu’on y trouvait.
En fait, ce protocole est très modulaire (et surtout très casse bonbons). J’ai fait pas mal de réseau au niveau pro, et je pense que c’est un des protos les plus tordus que j’ai pu voir jusqu’à maintenant, du fait de sa modularité, ainsi que des différentes specs rajoutées au fil du temps.
Bon, du coup, l’idée, c’est de comprendre le fonctionnement générique de ce protocole, et non pas juste de voir quelques paquets en dur comme on a fait jusqu’à présent.
Quand je dis comprendre, c’est en partie car il serait trop long de tout expliquer. En fait, chaque champ va en fait définir un subset de champs, et pareil pour chaque paramètre du subset, ce qui peut créer une ramification assez… tordue ! Disons le autrement : c’est le bordel. Je répète : LE BORDEL.
Gentle reminder : ici, on lit les octets en little endian.
L’idée principale, c’est que CHAQUE paquet envoyé en wifi contient un en-tête 802.11. Pour que tout fonctionne correctement, il doit être normé. Ainsi, la première partie de la frame s’appelle le MAC header, et on retrouvera toujours en première position un champ Frame Control, codé sur deux octets. Ce champ est EXTREMEMENT important, puisque c’est lui qui définir les champs suivants. Il se divise en 3 parties :
- Les bits 6 et 7 correspondent à la version du protocole. La doc 802.11 définit que la version est actuellement 0. Donc, hormis un bug/attaque/autre, ces bits ne changent pas et seront à 00
- Les bits 4 et 5 correspondent au type de paquet. Il en existe 4 :
- Management (bits 00) : Ils permettent d’envoyer des “commandes” entre la station et l’AP. Typiquement les probes, les authentications et les associations sont de type management
- Control (bits 01) : Ils servent à contrôler que tout se passe bien. On trouve les ACKnowledgement, mais aussi d’autres (comme les RTS, qui servent à demander la parole sur le réseau)
- Data (bits 10) : Ils contiennent les données des couches supérieures du modèle OSI (ARP, IP, TCP, HTTP, etc) et seront donc envoyées à la stack réseau
- Extension (bits 11) : Ils sont utilisé pour étendre les fonctionnalités, mais on va pas s’embéter avec ça.
- Les bits 0 à 3 correspondent au sous-type de paquet. Je ne vais pas tous les lister parce qu’il en existe beaucoup, mais on trouve par exemple :
- Association Request (bits 0000)
- Association Response (bits 0001)
- Authentication (bits 1011)
- Request To Send (RTS) (bits 1011)
On remarque au passage qu’un sous type RTS et Authentication ont les mêmes bits. C’est normal : puisque le type (les bits 4 et 5) est différent, ils ne se marchent pas sur les pieds :)
Ainsi, si je veux envoyer une requête d’authentification, mon Frame Control correspondra à :
- Version 0 : bits 00
- Type Management : bits 00
- Sous type Authentication : bits 1011
On aura ainsi un octet 1011 00 00, soit 0x0b.
A l’inverse, pour un paquet RTS, le Frame Control sera :
- Version 0 : bits 00
- Type Management : bits 01
- Sous type Authentication : bits 1011
Ce qui nous donne 1011 01 00, soit 0xb4.
Le deuxième octet du Frame Control est dépendant du premier. Si le type est de 1 et le sous type de 6, on est dans une frame Control/Extension, et les paramètres seront donc spécifiques à l’extension. On va pas trop y toucher dans cet article (ni dans aucun autre d’ailleurs :) ), parce que c’est déjà assez bordélique au niveau du fonctionnement basique.
Pour tous les autres types/sous types, on retrouvera une liste fixe de paramètres :
- To DS (Distribution System) : avec le champ suivant, cela permet en gros de savoir si une machine veut discuter sur le réseau avec une autre machine, ou si c’est de la communication entre l’AP et la station. Plus de détails ici.
- From DS : bah du coup, faut lire l’explication du champ précédent :)
- More Fragment : mis à 1 s’il reste d’autres paquets pour un message donné (c’est la fragmentation réseau : un paquet à une taille définie et si le message a envoyer est plus long, on le coupe en plusieurs paquets)
- Retry : mis à 1 si le paquet a été ré-émis une seconde fois par la source (donc si celle ci n’a pas reçu de ACK)
- Power Management : pour tout ce qui est gestion de la batterie des machines. Le wifi étant utilisé pour des postes nomades, un gestion de l’énergie a été mise en place dans les specs
- More Data : ce bit est également utilisé pour la gestion d’énergie et indique que des données sont sur l’AP, en attente d’envoi vers le supplicant.
- Protected Frame : assez explicite :) Ce champ est mis à 1 quand le payload du paquet est chiffré via WEP/WPA/WPA2. On le retrouve dans dans les frames datas par exemple
- +HTC/Order : c’est un champ un peu bâtard. On met le +HTC (High Throughput Control) à 1 dans les frames de type Control Wrapper. Ce type de frame a surement une utilité. Mais je sais pas laquelle. Lorsque le paquet n’est pas un Control Wrapper, il sert à ordonnancer les frames QoS.
On voit donc que ces deux premiers octets vont définir le comportement global de la frame. Maintenant, attelons nous aux autres champs. Comme dit plus haut, je ne vais pas TOUT détailler, puisqu’il existe beaucoup de combinaisons possibles, en fonction du type/sous type.
Ensuite, toujours dans le MAC header, on trouve le champ Duration/ID, d’une taille de 2 octets. Ce champ est fonction du type/sous type, et peut avoir quatre types de valeurs possibles. Je résume rapidement parce que la définition complète de ce champ fait 4 pages dans la doc (oui oui. Quatre), mais en gros, il correspond soit à l’Association ID (dont j’ai parlé plus haut), soit à une durée pour envoyer un ACK, soit à une valeur fixe de 32768.
Suite à ce Duration/ID, viennent les champs Addresses. Généralement, dans un paquet, on trouve un tuple de deux adresses (MAC source et dest, IP source et dest, etc). Là non. On peut en avoir entre une et quatre. Pourquoi jusqu’à quatre adresses ? Et bien en fait, c’est logique :
- la Receiving Address (RA) : l’adresse MAC de la machine qui recoit le paquet
- la Transmitting Address (TA) : l’adresse MAC de la machine qui transmet le paquet.
- la Source Address (SA) : l’adresse MAC de la machine source
- la Destination Address (DA) : l’adresse MAC de la machine qu’on cherche à joindre (un autre poste du LAN ou la gateway)
Ici quelques explications s’imposent : Dans un réseau Wifi, il n’y a pas forcément qu’une seule borne. Il est fréquent que plusieurs bornes utilisent le même réseau wifi. Ainsi, si ma bécane veut discuter avec google, elle va envoyer un paquet à la borne sur laquelle elle est connectée avec sa propre MAC comme SA et la gateway comme DA (bah oui, on discute avec la GW, pas avec google directement). Le champ TA sera également celui de mon laptop, et le champ RA sera la MAC de la borne wifi. Si cette borne est juste un relais, elle va donc devoir envoyer ce paquet à une seconde borne. A ce moment, elle va changer les champs TA et RA. TA deviendra donc l’addresse de la première borne et SA celle de la seconde borne. Cette deuxième AP va ensuite envoyer le paquet à la gateway. Lorsque la réponse arrivera, le chemin inverse sera effectué. Cela dit, un beau schéma, c’est toujours mieux :
Comme toujours les champs addresses correspondent aux types et sous type. Par exemple, les frames de controle n’ont pas besoin des 4, puisque l’AP communique directement avec mon PC.
On peut dans certaines trames également trouver le champ BSS ID qui correspond à la MAC de l’AP.
Ce champ se divise en deux parties : une première de 4 bits qui indique le numéro de fragmentation, et une seconde de 12 bits qui est le numéro de séquence. Qui est… bah un numéro quoi. qui s’incrémente et tout.
ENFIN ! ON arrive au Frame Body (c’est pas trop tôt, l’article est commencé depuis 3 mois). Le Frame Body a toujours une taille variable. Tout simplement parce qu’il est inhérent à chaque paquet.
Pour les frames de types données, c’est plutôt simple : on envoie la sauce, avec toutes les couches OSI supérieures (mais si lecteur, tu sais bien, le truc qu’on appelle IP par exemple). Là, il n’y a pas à débattre, tout ce qui est envoyé ici n’a aucun rapport avec le 802.11. La taille peut aller de 0 à 2304 octets. Si on a un message plus gros à faire passer, on doit mettre le bit More Fragments à 1. Une fois que le paquet est reçu, la stack réseau prend le relais et envoie le paquet au niveau applicatif.
Ensuite, les frames de type management et controle : vous connaissez le refrain maintenant : “Ca dépend du type et du sous type”. On ne change pas une équipe qui gagne.
EN fait, des exemples, j’en ai déjà donné plusieurs tout au long de l’article : les probes, les authentications, les associations, etc. Ici la taille est en fonction des paramètres envoyés. Elle peut avoir une taille qui va de 0 (pour les types ACK par exemple) à 2304. Cela dit, on a rarement 2304 octets des paramètres à envoyer d’un coup ! ^^
Après le Frame Body, on trouve le truc le plus simple du proto : le Fram Check Sequence (FCS). C’est toujours un champ de 4 octets, qui contient un CRC32 du MAC header et du Frame Body. Les plus malins auront compris qu’il sert à vérifier l’intégrité du paquet :) Si le CRC32 est bon, le paquet est accepté et transmis vers la destination. Dans ce cas, un ACK est envoyé à la source pour dire “wesh gros, j’ai fait passer ton petit mot”. Si le FCS est faux, c’est qu’il y a eu erreur. A ce moment, l’AP ne prévient même pas qu’il y a eu un souci. Du coup, mon PC attend un certain moment, puis renvoie le paquet avec le champ Retry à 1.
Conclusion
Pfiouuu, c’était compliqué. 3500 pages à se taper (bon pas tout quand même, j’ai fait pas mal de Ctrl + F), des recherches dans les tréfonds des internets du web, un article de plus de 30000 caractères, mais bon, au moins, je sais ce qui se passe le matin, quand mon laptop boote et que je bois mon café :)
En tout cas, même si j’ai galeré, j’ai beaucoup appris techniquement, c’est un très bon exercice à faire, et j’espère que vous aurez aussi appris 2 ou 3 choses !
Oh, et du coup, suite à KRACK, la Wi Fi Alliance a décidé de faire bouger les choses avec la mise en place du WPA3. A cela, deux solutions : soit ils vont updater les specs pour rajouter toujours plus de bazar, soit ils vont créer une nouvelle spec from scratch, et cet article ne sera bientôt plus utile ^^
Enjoy
The lsd
Liens utiles
Tous les liens qui m’ont servi à comprendre le 802.11
- ieeexplore.ieee.org : le lien vers la doc officielle, évidemment. Attention par contre, il faut s’inscire
- mrncciew.com : une bible. C’est pas super beau, un peu brouillon, mais beaucoup d’infos !
- www.cwnp.com : un forum dédié au wifi. C’est le site officiel de la certif CWNP, donc il y a des infos de qualité
- meraki.com : un résumé high level des étapes de connexion
- cisco.com : de la doc sur les méthodes de chiffrement
- cisco.com : quelques explications sur les frames d’authentification
- arubanetworks.com : des explications un peu plus détaillées que moi sur le RSN et TSN (Transitional Security Network, un truc qui a servi à passer de WEP à WPA2)
- fiddy.free.fr : explications détaillées en en français sur le chiffrement WEP, et pourquoi c’est tout pété
- Fichiers utiles : Des pcap épuré pour pouvoir regarder le détail, et un html avec les schémas de la struct