Lsd Security Daemon
LSD Security Daemon

Le Wifi, comment ça marche 1/2

Bon, maintenant qu’on a expliqué KRACK dans les détails, on va gratter un peu la surface et regarder comment fonctionne le mécanisme de connexion dans sa globalité.
Lorsqu’on se connecte sur une borne wifi, il se passe en réalité plein de choses under the hood, dont personne ne se rend compte.
Le but de cet article est donc de démystifier un peu le fonctionnement d’une connexion classique à un AP, ce qui va permettre de préparer le terrain pour le post suivant, qui expliquera comment faire des bidouilles sympas (par exemple du jamming).

Généralités

Avant de commencer, je pose quelques détails généraux, histoire qu’on parte sur de bonnes bases :)

Une chose importante à prendre en compte, c’est qu’on est sur du réseau wifi. Qui dit wifi dit ondes. Et qui dit ondes dit (forcément) écoute via le mode monitor des cartes wifi. Pour expliquer un peu , il existe 4 modes au niveau wifi :

  • le mode classique, que tout le monde utilise. J’utilise le mot classique par défaut, je ne sais pas s’il y a un mot plus exact
  • le mode promiscuous (qui existe également au niveau cablé). Ce mode permet de récupérer tous les paquets qui ne nous sont pas adressés directement (qui n’ont pas comme adresse de destination notre MAC techniquement). Ce mode s’utilise lorsqu’on est déjà connecté à un réseau wifi
  • le mode monitor (pour le coup, il n’y a pas d’équivalent cablé) qui nous donne la possibilité de récupérer littérallement TOUS les paquets. C’est grâce à ce mode qu’on va pouvoir faire des trucs cools (au hasard péter des clés wifi)
  • le mode injection, qui permet d’aller encore plus loin que le monitor. Avec ce mode, on peut envoyer des paquets alors même qu’aucun réseau wifi n’est connecté avec la carte. En gros, on peut envoyer tout et n’importe quoi. Là aussi, c’est plutôt cool pour certaines attaques.

Dans cet article, les paquets que je montre sont des versions “figées”, c’est à dire spécifiques à chaque type de trame. Les termes mis en gras dans les images des trames sont les plus importants et donc ceux que j’explique. J’ai mis également des screenshots wireshark pour la gloire, histoire de voir concrètement la gueule des paquets.
J’explique en fin de post le fonctionnement générique des trames 802.11. J’dis ça, j’dis rien, mais pour comprendre le réseau, vaut mieux aller lire les détails :)

Les puristes du réseau pourront me rétorquer qu’il existe des différences entre une trame et un paquet. Ma réponse est simple : osef. D’une part parce qu’on arrive très bien à comprendre l’idée générale, et d’autre part pour éviter des répétitions dans tous les sens.

Oh, et n’oublions pas aussi que la doc fait quand même TROIS MILLES CINQ CENT PAGES. Il est donc possible que je me sois planté à certains endroits, dans ce cas, il ne faut pas hésiter à me corriger :)

Découverte

9h du matin : j’allume mon laptop, la séquence de boot passe tranquillement pendant que je bois mon café, et quand je reviens devant mon PC, mon network manager me propose une liste de wifi sur lequel me connecter. OK c’est cool, je choisis mon réseau, la connexion se fait, et je commence ma journée de boulot.
Mais du coup… il s’est passé quoi exactement ?

Et bien dans un premier temps, mon laptop a envoyé un gros paquet des familles, qui dit plus ou moins :

“HEY HO ! ON SE REVEILLE LES ACCESS POINT ! MOI DE MON COTÉ, JE PEUX COMPRENDRE SI VOUS ME PARLEZ FRANCAIS OU ANGLAIS”.

Ce paquet, c’est ce qu’on appelle un Probe Request.
Pour expliquer plus sérieusement, mon portable a fait une requête en broadcast (donc à destination de tout le monde) afin d’annoncer à tous les réseaux alentours qu’il a besoin de se connecter à un wifi, et qu’il peut utiliser certains paramètres (au hasard, la version A/B/G/N, mais également d’autres).
Evidemment, les paquets de ce genre sont normés, grâce au standard 802.11, et ressemblent techniquement à cela :

Probe Reponse

Probe Reponse Wireshark

Je ne vais pas expliquer tous les champs, mais pour faire simple, on a ici 4 informations importantes (il y en a d’autres évidemment) :

  • le Frame Control : une valeur de 0x0004 correspond à un paquet de type probe request.
  • la Destination Address : l’adresse MAC de la borne wifi à qui le paquet est envoyé. Je disais plus haut que les probes requests envoyaient en broadcast, mais il est aussi possible d’envoyer en unicast (vers une seule machine), ici 00:0E:9E:51:AC:11. Ca permet de moins congestionner le réseau.
  • la Source Address : l’adresse MAC de mon portable, afin que les AP puissent me répondre.
  • le Frame Body : alors là, c’est un peu le bordel, parce que les normes wifi ont évolué au fil du temps. Du coup, les paramètres renseignés dans le Frame Body sont carrément variables. Dans la version 2016 de la norme 802.11, on trouve jusqu’à 20 champs (tableau 9.33, page 706). Chaque champ se compose de 3 parties : un ID, la taille du champ, et sa valeur. Ils permettent de définir les capacités du supplicant (le client Wifi), afin que l’AP sache s’il pourra répondre ou non. On retrouve comme informations, les channels utilisables, les taux de transfert, et en fonction de pas mal de paramètres, d’autres informations.

Pour information, tout ce qui précède le Frame Body est appelé le MAC Header. On n’en reparlera pas, mais sachez le :)
De plus, le Frame Body est différent selon les paquets. Ici, on a uniquement des paramètres taggués. Comme on ne peut pas savoir à l’avance quels paramètres seront présents, on est obligé d’utiliser un principe de tags pour chaque champ (d’où l’utilisation d’ID). Le Frame Body étant spécifique selon les paquets, cela ne sera pas toujours le cas. On pourra trouver des paramètres fixes (donc pas besoin d’ID). Don’t worry, j’explique tout bien komilfo à la fin.

Bref. Une fois que cette étape est passée, les AP qui sont à portée vont répondre à ma machine deux choses :
La première, c’est :

“Ok mec, pas la peine de crier, je t’ai entendu.”

C’est l’ACK (ACKnowledgment) que l’AP envoie au supplicant, juste pour valider que le message a bien été reçu.
C’est un paquet très court, qui ne contient quasiment rien. Il est tellement court, qu’il ne contient même pas l’adresse MAC de la source ! Après quelques recherches, on explique ici, et dans le §9.2.8 de la doc que c’est normal qu’il n’y ait pas de source parce que l’AP ne peut répondre qu’à une seule machine pendant un court laps de temps, grâce à un timer. Du coup, on sait forcément à qui s’adresse le ACK et ça fait un paquet plus court à envoyer.
Voilà à quoi ressemble un ACK :

ACK packet

ACK packet Wireshark

Au niveau des infos, c’est plus simple, vu que le but du jeu, c’est juste que l’AP dise que le message est bien arrivé. Dans les champs utiles, on a simplement :

  • un Frame Control qui correspond à 0x00D4,
  • l’adresse de destination, qui est donc l’adresse source du probe request.

Ce message apparait quasiment après chaque paquet reçu, je n’en parlerai plus à partir de maintenant, mais il faut garder en tête qu’il est (presque) toujours présent.

La deuxième chose, c’est ça :

“Toi et moi, c’est un match, tiens voilà mes infos si tu veux qu’on discute ensemble”.

C’est le Probe Response. Techniquement, il contient, comme pour la requête, plusieurs informations utiles au client (nom du constructeur, SSID, channel, etc) et ressemble beaucoup au Probe Request :

Probe Response

Probe Response Wireshark

Dans la liste des champs intéressants, on retrouve les mêmes choses que pour le probe request (Frame Control, Destination, Source, Body).
Evidemment, les MAC source et destination sont inversées, et le Frame Body est différent. Celui-ci, encore une fois très important, donne des informations, comme le type de chiffrement utilisé (j’en reparle un peu plus loin), qui permettent à mon PC de savoir s’il est en capacité de se connecter à cet AP.

Bon, maintenant que les réponses des bornes ont été récupérées par ma machine, elle décide quel est le meilleur réseau auquel se connecter, en fonction de plusieurs paramètres, du genre la puissance du signal, le réseau préféré, ou encore le débit proposé. Libre à l’OS de choisir ce qu’il veut. Le mien, par exemple, a une fâcheuse tendance à choisir le réseau le plus pourri. Une fois que le choix est fait, on va passer à la phase suivante : l’authentification.

Authentification

On a découvert les réseaux à proximité, on va donc pouvoir s’attaquer à la deuxième étape : l’authentification.
Une fois que le supplicant a choisi son AP, il va devoir lui dire qu’il veut se connecter. Et alors là… C’est le bordel. Grave.

Pour s’authentifier, le client va donc envoyer une première requête. Cette requête va contenir un élément important : le type d’authentification. Soit Open, soit Shared Key. Bêtement, on pourrait penser que Open correspond aux réseaux ouverts (wifi mcdo ou autres), et que Shared Key correspondrait aux wifi authentifié (WEP et WPA/WPA2). MAIS NON.
La blague dans l’histoire, c’est que :

  • Shared Key correspond à du chiffrement WEP,et uniquement à du WEP (§12.3.3.3.1 de la doc 802.11)
  • Open correspond à un wifi ouvert… ou alors à du chiffrement via WPA/WPA2. Les maux de têtes commencent à arriver ? Ce n’est que le début.

C’est débile, oui, mais pourquoi ? En fait, à la mise en place de la norme 802.11, les créateurs n’ont prévu à la base que de wifi non chiffré, ou chiffré en WEP. Du coup, il faut prendre en compte que tout ce qui n’est pas WEP, est Open.

Maintenant, comment mon ordinateur sait que l’AP m’a proposé du non chiffré, du WEP, du WPA, ou du WPA2 ?
A la base, c’était simple. Le Probe Response contenait un champ Privacy (un bit mis à 1) qui définissait ou non l’utilisation du WEP. Et puis, ce fut le drame.
Lorsque l’IEEE s’est rendu compte que WEP était pété, il ont sorti un truc à l’arrache, histoire colmater un peu : le WPA. Ce WPA utilise un chiffrement de type TKIP.
SAUF QUE, comme il a été fait un peu à la wanagain bistoufly, les mecs se sont dit qu’ils allaient préparer un truc plus propre pour la suite : WPA2, qui utilise du CCMP.
SAUF QUE, histoire que tout soit bien retrocompatible, quand ils ont fait l’amendement 802.11i (qui officialise WPA/WPA2), les bonhommes ont décidé que WPA devrait AUSSI supporter CCMP, et que WPA2 devrait AUSSI supporter TKIP.
SAUF QUE, encore une fois, histoire de compatibilité, il a fallu faire des bidouilles from space. Donc, pour WPA, il a fallu utiliser un paramètre optionnel spécifique (le tag 221) qui liste les chiffrements disponibles en WPA. Pour WPA2, ils ont créé un autre paramètre : le RSN (Robust Security Network). (Evidemment, trouver ça dans 3500 pages de doc… bisou.)

Donc, pour résumer le fonctionnement, dans le Probe Response, ça se passe comme ça :

  • Mode Shared : WEP
  • Mode Open :
    • tag RSN :
      • CCMP et/ou TKIP (mode WPA2)
    • tag optionnel 221 :
      • CCMP et/ou TKIP (mode WPA)
    • aucun tag :
      • wifi non chiffré

En fonction de ces informations, ma bécane saura ainsi lors de cette première requête de la phase d’authentification s’il faut envoyer une demande Shared ou Open.

On va commencer par étudier le type Open, c’est le plus simple :)
La requête qu’envoie mon PC, c’est littéralement :

“Hey, psst, hey ! Tu me laisses rentrer s’il te plait ?”

Comme d’hab, je met le petit schéma de la requête. Pour le coup, j’ai détaillé le Frame Body parce qu’il est important de comprendre ce qu’il contient.

Open Authentication request

Open Authentication request Wireshark

Tout se joue donc au niveau du Frame Body. En mode Open, on trouve trois champs :

  • l’Authentication algorithm : qui correspond à 0x0000
  • l’Authentication SEQuence : puisque c’est le premier message de l’authent, il correspond à 0x0001
  • le Status Code : tout se passe bien, il est à 0x0000

Une fois que l’AP a reçu ce message d’authentification, il va bien évidemment y répondre. La réponse est quasiment identique à la requête. Dans le Frame Body, le seul champ différent est l’Authentication SEQuence qui passe à 0x0002. Le reste ne bouge pas, si tout se passe bien :

Open Authentication response

Open Authentication response Wireshark

Une fois que la réponse est envoyée au client (et que l’AP a bien reçu le ACK qui suit), tout est ok, les deux machines sont dans un état authentifié, mais non associé. Je parle de l’association après, mais pour l’instant, étudions un peu l’authentification en mode Shared.

En mode Shared (donc WEP), il y a un 4Way handshake, qui permet de valider la clé Wifi, sans qu’elle ne passe en clair sur le réseau (bon, le WEP a été pété malgré ça, mais l’intention était louable :) )
Le premier message est, à l’instar du mode Open, envoyé par le client et est identique, hormis l’Authentication Algorithm, qui correspond cette fois-ci à 0x0001, pour signifier le mode Shared. Malheureusement, je n’ai pas d’équipements qui me permette de faire d’authent WEP sous la main, donc j’ai honteusement (ou pas) “emprunté” des images venant de mrncciew.com. On lui dit merci :)

Shared Authentication request

Shared Authentication request Wireshark

Le second message, envoyé par l’AP, va faire les actions suivantes : incrémenter le numéro de séquence pour le passer à 0x0002, et envoyer un paramètre taggué (id 16), qui correspond à un challenge que ma machine devra utiliser pour valider la clé Wifi. La valeur de ce challenge est une chaine pseudo aléatoire de 128 octets.

Shared Authentication challenge Wireshark

Un troisième message va être envoyé par le supplicant. Celui ci va contenir principalement :

  • l’Initialization Vector (IV), qui permet d’éviter d’avoir deux messages chiffrés identiques pour un même clair
  • l’Integrity Check Value (ICV), qui est un bête CRC32 du challenge clair
  • le challenge response, qui est (IV + challenge) chiffré avec la clé WEP.

Shared Authentication challenge validation Wireshark

Une fois ce message reçu par l’AP, ce dernier va déchiffrer le challenge, vérifier qu’il correspond bien à son ICV, et vérifier qu’il correspond au clair envoyé dans le message 2.
Si le challenge et sa réponse sont équivalents, l’AP va donc envoyer un dernier message de validation, les données du Frame Body seront classiques : l’Authentication Algorithm toujours positionné à Shared Key, l’Authentication SEQuence à 0x0004, et le Status Code à 0x0000.

Shared Authentication response

Shared Authentication response Wireshark

A l’inverse, s’il y a un souci (mauvaise clé par exemple), le Status Code sera différent de 0x0000 et l’AP considérera que le client n’a pas pu s’authentifier.
Ouf, next step !

Pour la suite, c’est par ici

Enjoy

The lsd