Consulting, services, computer engineering. Implementation of technology solutions and support for businesses.

User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 

     

    Comment se protéger d'una attaque man in the middle windows NTLM ?

     

     

     

     

    Pour rappel, le protocole NTLM est utilisé pour authentifier un client auprès d’un serveur. Ce qu’on appelle client et serveur sont les deux parties de l’échange. Le client est celui qui souhaite s’authentifier, et le serveur est celui qui valide, ou non, l’authentification du client.

     

    Cette authentification se déroule en 3 étapes :

      Ce procédé s’appelle challenge/response.

      L’intérêt de cet échange, c’est que le secret de l’utilisateur ne transite jamais sur le réseau

       

      Attaque man in the middle windows NTLM, le relai NTLM

       

      Avec ces informations, nous pouvons aisément imaginer le scénario suivant : Un attaquant arrive à se positionner entre le client et le serveur, et ne fait que relayer les informations de l’un vers l’autre.

      Comme il est en position d’homme du milieu, cela signifie que du point de vue du client, la machine de l’attaquant est le serveur auprès duquel il souhaite s’authentifier, et du point de vue du serveur, l’attaquant est un client comme un autre qui souhaite s’authentifier.

      Sauf que l’attaquant ne souhaite pas “juste” s’authentifier auprès du serveur. Il souhaite le faire en se faisant passer pour le client. Or, il ne connait pas le secret du client, et même s’il écoute les conversations, comme ce secret n’est jamais transmis sur le réseau, l’attaquant n’est pas en mesure d’extraire un quelconque secret pour ensuite s’authentifier auprès du serveur. Mais alors, comment ça fonctionne ?

       

      Attaque man in the middle windows NTLM: relai de messages

       

      Lors d’une authentification NTLM, un client peut prouver à un serveur qu’il est bien qui il prétend être, et pour cela, il chiffre une information fournie par le serveur en utilisant son mot de passe. L’idée est alors que l’attaquant va se positionner en “passe plat”, en laissant le client travailler, et en passant les plats du client vers le serveur, et les réponse du serveur vers le client.

      Tout ce que le client doit envoyer au serveur, c’est l’attaquant qui le recevra, et il renverra les messages tels quels au vrai serveur, et tous les messages que le serveur envoie au client, c’est également l’attaquant qui les recevra, et ils les transmettra au client, tels quels.

      Et tout ça, ça fonctionne bien ! En effet, du point de vue du client, donc la partie de gauche sur le schéma, une authentification NTLM a lieu entre l’attaquant et lui, avec toutes les briques nécessaires. Le client envoie une demande d’authentification dans son premier message, ce à quoi l’attaquant répond avec un défi, ou challenge. En recevant ce challenge, le client construit sa réponse à l’aide de son secret, et envoie finalement le dernier message de l’authentification contenant notamment le challenge chiffré.

      En l’état, l’attaquant ne peut (presque) rien faire de cet échange. Mais heureusement, il y a la partie droite du schéma. En effet, du point de vue du serveur, l’attaquant est un client comme un autre. Il a envoyé un premier message pour demander à s’authentifier, et le serveur a répondu avec un challenge. Comme l’attaquant a envoyé ce même challenge au vrai client, le vrai client a chiffré ce challenge avec son secret, et a répondu avec une réponse valide. L’attaquant peut donc envoyer cette réponse valide au serveur.

      C’est là que réside tout l’intérêt de cette attaque. En effet, du point de vue du serveur, l’attaquant s’est authentifié auprès de lui en utilisant le secret de la victime, mais cela de manière transparente pour le serveur. Il n’a aucune idée du fait que l’attaquant rejouait ses réponses auprès du client pour que le client lui donne les bonnes réponses.

      Ainsi, du point de vue du serveur, voilà ce qu’il s’est passé :

      A la fin de ces échanges, l’attaquant est authentifié sur le serveur avec les identifiants du client.

       

      Attaque man in the middle windows NTLM:  Net-NTLMv1 et Net-NTLMv2

       

      Pour information, c’est cette réponse valide relayée par l’attaquant dans le message 3, donc le chiffrement du challenge avec le secret, qu’on appelle communément le hash Net-NTLMv1 ou Net-NTLMv2, mais qu’on appellera ici Hash NTLMv1 ou Hash NTLMv2, comme indiqué dans le paragraphe préliminaire.

      Pour être exact, ce n’est pas tout à fait le chiffrement du challenge, mais un condensat qui utilise le secret du client. C’est la fonction HMAC_MD5 qui est par exemple. On peut tenter de casser ce type de hash par force brute. La cryptographie associée au est obsolète, et le hash NT qui a servi à créer le hash peut être retrouvé très rapidement. En revanche pour NTLMv2 ça prend beaucoup plus de temps. Il est donc préférable et conseillé de ne pas autoriser les authentification avec NTLMv1 sur un réseau de production.

       

      Attaque man in the middle windows NTLM: : En pratique

       

      A titre d’exemple, j’ai monté un petit lab avec plusieurs machines. Il y a notamment un client DESKTOP01 dont l’adresse IP est 192.168.56.221 et un serveur WEB01 avec comme IP 192.168.56.211. Ma machine est celle de l’attaquant, avec l’adresse IP 192.168.56.1. Nous nous trouvons donc dans la situation suivante :

      L’attaquant a donc réussi à se mettre en position d’homme du milieu. Il existe différentes techniques pour y parvenir, que ce soit via un abus des configurations par défaut de IPv6 dans un environnement Windows, ou des protocoles LLMNR et NBT-NS. Quoiqu’il en soit, l’attaquant fait croire au client que c’est lui, le serveur. Ainsi, lorsque le client tente de s’authentifier, c’est auprès de l’attaquant qu’il va effectuer cette opération.

      L’outil que j’utilise pour effectuer cette attaque est , outil présent dans la suite Impacket. Cet outil est présenté en détails dans par le développeur de Impacket.

      L’outil crée différents serveurs, dont un serveur SMB pour cet exemple, et il écoute dessus. S’il reçoit une connexion sur ce serveur, il relaiera cette connexion vers la cible que nous lui fournissons, soit 192.168.56.221 dans cet exemple.

      D’un point de vue réseau, voici une capture de l’échange, avec l’attaquant qui relaie les informations vers la cible.

      En vert se trouvent les échanges entre le client DESKTOP01 et l’attaquant, et en rouge les échanges entre l’attaquant et le serveur WEB01. Nous voyons bien les 3 messages effectués entre DESKTOP01 et l’attaquant, et entre l’attaquant et le serveur WEB01.

      Et pour bien comprendre la notion de relai, nous pouvons vérifier que lorsque le serveur WEB01 envoie un challenge à l’attaquant, l’attaquant renvoie exactement la même chose au client DESKTOP01.

      Voilà le challenge envoyé par WEB01 à l’attaquant :

      Lorsque l’attaquant reçoit ce challenge, il l’envoie à son tour, sans le modifier, au client DESKTOP01. Dans cet exemple, le challenge est , et il est transmis au client :

      Le client va alors calculer la réponse en utilisant son secret, comme nous l’avons vu dans les paragraphes précédents, et il va envoyer cette réponse en indiquant qui il est (jsnow), sur quelle machine il se trouve (DESKTOP01), et dans cet exemple il indique que c’est un utilisateur du domaine, donc il fournit le nom du domaine (ADSEC).

      L’attaquant qui reçoit tout ça ne se pose pas de questions. Il envoie exactement les mêmes informations au serveur. Il prétend donc être l’utilisateur jsnow sur la machine DESKTOP01 et faisant partie du domaine ADSEC, et il envoie également la réponse qui a été calculée par le client, appelée NTLM Response dans ces captures d’écran, mais que nous pouvons également appeler Hash NTLMv2.

      Nous voyons bien que l’attaquant a joué le rôle de relai dans cet échange. Il n’a fait que passer les informations du client vers le serveur et vice versa, sauf qu’in fine, le serveur pense que l’attaquant s’est authentifié avec succès, et l’attaquant peut alors effectuer des actions sur le serveur en se faisant passer pour ADSEC\jsnow.

       

      Attaque man in the middle windows NTLM: Authentification vs Session

       

      Maintenant que nous avons compris le principe de base du relai NTLM, la question qui se pose est de savoir comment, concrètement, est-ce qu’on peut effectuer des actions sur un serveur après avoir relayé l’authentification NTLM ? D’ailleurs, qu’entend-on par “actions” ? Qu’est-il possible de faire ?

      Pour répondre à cette question, il faut d’abord éclaircir une chose fondamentale. Lorsqu’un client s’authentifie auprès d’un serveur pour y faire quelque chose, nous devons distinguer deux choses

        Ainsi, si le client s’est correctement authentifié, il pourra alors accéder aux ressources proposées par le serveur, telles que les partages réseau, l’accès à un annuaire LDAP, un serveur HTTP ou encore une base de données SQL. Cette liste n’est évidemment pas exhaustive.

        Pour gérer ces deux étapes, il faut que le protocole utilisé puisse encapsuler l’authentification, donc l’échange des messages NTLM.

        Bien entendu, si tous les protocoles devaient intégrer le fonctionnement de NTLM, ça deviendrait rapidement un joyeux bazar. C’est pourquoi Microsoft met à disposition une interface sur laquelle il est possible de se reposer pour gérer l’authentification, et des paquets ont été spécialement développés pour gérer différents types d’authentification.

         

        Attaque man in the middle windows NTLM: SSPI & NTLMSSP

         

        L’interface SSPI, ou Security Support Provider Interface, est une interface proposée par Microsoft permettant d’uniformiser l’authentification, quel que soit le type d’authentification utilisé. Différents paquets peuvent se brancher sur cette interface afin de gérer différents types d’authentification.

        Dans notre cas, c’est le paquet NTLMSSP (NTLM Security Support Provider) qui nous intéresse, mais il y a également un paquet pour l’authentification Kerberos, par exemple.

        Sans rentrer dans les détails, l’interface SSPI met à disposition plusieurs fonctions.

        Lors d’une authentification NTLM, le client et le serveur vont faire appel à ces différentes fonctions. Les étapes ne sont décrites que succintement ici.

          La raison pour laquelle ces étapes sont expliquées, c’est pour montrer qu’en réalité, du point de vue du client ou du serveur, la structure des 3 messages qui sont échangés n’a pas d’importance. Nous savons, nous, avec les connaissances du protocole NTLM, à quoi correspondent ces messages, mais le client comme le serveur n’en ont rien à faire. Ces messages sont d’ailleurs décrits dans la documentation Microsoft comme des jetons opaques, ou opaque tokens.

          Cela signifie que ces 5 étapes sont totalement indépendantes du type de client, ou du type de serveur. Elles fonctionnent quel que soit le protocole utilisé pourvu que le protocole ait quelque chose de prévu pour permettre d’échanger d’une manière ou d’une autre cette structure opaque du client vers le serveur.

          Les protocoles se sont donc adaptés pour trouver un moyen de caler une structure NTLMSSP, Kerberos, ou autre, dans un champ précis, et si le client ou le serveur voit qu’il y a de la donnée dans ce champ, il ne fait que la passer à ou .

          Ce point est assez important, puisqu’il montre clairement que la couche applicative (HTTP, SMB, SQL, …) est complètement indépendante de la couche d’authentification (NTLM, Kerberos, …). Par conséquent, il faut des mesures de sécurité et pour la couche d’authentification, et pour la couche applicative.

          Pour mieux comprendre, nous allons voir les deux exemples de protocoles applicatifs SMB et HTTP. Il est assez facile de trouver de la documentation pour les autres protocoles, c’est un peu toujours le même principe.

           

          Attaque man in the middle windows NTLM: Intégration avec HTTP

           

          Voilà à quoi ressemble une requête HTTP basique.

          Les éléments obligatoires dans cet exemple sont les suivants : le verbe HTTP (GET), la page demandée (index.html), la version du protocole (HTTP/1.1), ou l’en-tête Host.

          Mais il est tout à fait possible d’ajouter d’autres en-têtes arbitraires. Au mieux, le serveur distant est au courant que ces en-têtes seront présents, et il saura les gérer, et au pire il les ignorera. On peut ainsi avoir la même requête avec quelques informations en plus.

          C’est cette fonctionnalité qui est utilisée pour pouvoir transférer des messages NTLM du client vers le serveur. Il a été décidé que le client envoie ses messages dans un en-tête appelé et le serveur dans un en-tête appelé . Si jamais un client tente d’accéder à un site internet demandant une authentification, le serveur va répondre en ajoutant l’en-tête , et en mettant comme valeur les différents mécanismes d’authentification qu’il supporte. Pour NTLM, il indiquera tout simplement .

          Le client sachant qu’une authentification NTLM est nécessaire, va envoyer le premier message dans l’en-tête , encodé en base 64 car le message ne contient pas que des caractères imprimables. Le serveur répondra avec un challenge dans l’en-tête , le client calculera la réponse qu’il enverra dans et si l’authentification est acceptée, le serveur renverra un code de retour 200 indiquant que tout s’est correctement déroulé.

          Tant que la session TCP est ouverte, l’authentification sera effective. Dès que la session se termine, en revanche, le serveur web n’aura plus le contexte de sécurité du client, et une nouvelle authentification devra avoir lieu. Ca peut souvent arriver, et grâce aux mécanismes de SSO (Single Sign On) de Microsoft, c’est souvent transparent pour l’utilisateur.

           

          Attaque man in the middle windows NTLM: Intégration avec SMB

           

           

           

          Prenons un autre exemple fréquemment rencontré en entreprise. C’est le protocole SMB, utilisé pour accéder à des partages réseau, mais pas que.

          Le protocole SMB fonctionne en utilisant des commandes. Elles sont , il en existe un grand nombre. On peut noter par exemple , ou , des commandes permettant d’ouvrir, fermer ou lire un fichier.

          Et bien SMB possède également une commande dédiée à la configuration d’une session SMB, et cette commande est . au contenu des messages NTLM dans cette commande.

            Ce qu’il faut retenir, c’est qu’il existe une commande SMB spécifique possédant un espace dédié aux différents messages échangés lors d’une authentification NTLM.

            Voici un exemple de packet SMB contenant la réponse d’un serveur à une authentification.

            HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanmanServer\Parameters

            Ces deux exemples montrent bien que le contenu des messages NTLM est indépendant du protocole. Il peut être inclus dans n’importe quel protocole qui le supporte.

            Il est alors très important de bien distinguer la partie authentification, donc les échanges NTLM, de la partie applicative, ou la partie session, qui est la suite des échanges via le protocole utilisé une fois que le client est authentifié. Ca peut donc être la navigation sur le site internet via HTTP ou des manipulations de fichiers sur un partage réseau si on utilise SMB.

            Comme ces informations sont indépendantes, cela signifie qu’un attaquant en situation d’homme du milieu peut très bien recevoir une authentification via HTTP, par exemple, et la relayer vers un serveur mais en utilisant SMB. C’est ce qu’on appelle du relai cross-protocole.

            En ayant tous ces aspects en tête, les chapitres suivants vont mettre en lumière les différentes faiblesses existantes ou ayant existé, et les mécanismes de sécurité qui entrent en jeu pour les combler.

             

            Attaque man in the middle windows NTLM: Signature de la session

             

            Principe

            Une signature, c’est un mécanisme qui permet d’authentifier celui qui envoie un élément, et de garantir que cet élément n’a pas été modifié entre l’envoi et la réception. Par exemple, si l’utilisateur envoie le texte , et signe numériquement ce document, alors quiconque recevra ce document et sa signature pourra vérifier que c’est bien qui l’a édité, et sera assuré qu’il a bien écrit cette phrase, et pas une autre, puisque la signature garantit que le document n’a pas été modifié.

            Le principe de signature peut être appliqué à n’importe quel échange, pour peu que le protocole le supporte. C’est par exemple le cas de , et même de . En pratique, la signature des flux HTTP est rarement mise en place.

            Mais du coup, c’est quoi l’intérêt de signer des paquets ? Et bien comme discuté précédemment, la session et l’authentification sont deux étapes distinctes lorsqu’un client veut utiliser un service. Etant donné qu’un attaquant peut se placer en homme du milieu, et relayer les messages d’authentification, il peut se faire passer pour le client auprès du serveur.

            C’est là que la signature des flux entre en jeu. Même si l’attaquant a réussi à s’authentifier auprès du serveur en tant que le client, il ne sera pas en mesure, ensuite, indépendamment de l’authentification, de signer les paquets. En effet, pour pouvoir signer un paquet, il faut avoir connaissance du secret du signataire.

            Or dans le relai NTLM, l’attaquant veut se faire passer pour un client, mais il n’a pas connaissance de son secret. Il n’est donc pas en mesure de signer quoi que ce soit au nom du client. Comme il ne peut pas signer le paquet, le serveur recevant le paquet va soit voir que la signature n’est pas présente, soit qu’elle n’existe pas, et rejettera la demande de l’attaquant.

            Vous le comprenez donc bien, si les paquets doivent nécessairement être signés après l’authentification, alors l’attaquant ne peut plus opérer, puisqu’il n’a pas connaissance du secret du client. L’attaque échouera donc. C’est une mesure très efficace pour se protéger du relai NTLM.

            C’est très bien tout ça, mais comment est-ce que le client et le serveur se mettent d’accord sur le fait de signer ou non les paquets ? Et bien c’est une très bonne question. Oui, je sais, c’est moi qui la pose, mais ça n’enlève rien à sa pertinence.

            Pour cela, deux éléments entrent en jeu.

             

              Attaque man in the middle windows NTLM: Négociation

               

              Cette négociation permet de savoir si le client et/ou le serveur supportent la signature des flux (mais pas que), et se fait pendant l’échange NTLM. Donc je vous ai un peu menti tout à l’heure, les deux échanges ne sont pas complètement indépendants. (D’ailleurs, j’ai dit que comme c’était indépendant, on pouvait changer de protocole entre le client et le serveur, mais il y a des limites, nous les verrons dans le chapitre sur le MIC dans l’authentification NTLM.)

              En fait, dans les messages NTLM, il y a d’autres autres informations que le challenge et la réponse qui sont échangées. Il y a également des drapeaux de négociation, ou Negotiate Flags. Ces drapeaux indiquent ce que supporte l’entité qui les envoie.

              On trouve plusieurs drapeaux, mais celui qui nous intéresse ici c’est NEGOTIATE_SIGN.

              Lorsque ce drapeau est mis à 1 par le client, cela signifie que le client supporte la signature des flux. Attention, ça ne veut pas dire qu’il va forcément signer ses flux. Juste qu’il en est capable.

              De même lors de la réponse du serveur, s’il supporte la signature des flux alors le drapeau sera également positionné à 1.

              Cette négociation permet donc à chacune des deux parties, client et serveur, d’indiquer à l’autre s’il est en mesure de signer les flux. Pour certains protocoles, même si le client et le serveur supportent la signature, ce n’est pas pour autant que forcément les flux seront signés.

               

              Attaque man in the middle windows NTLM: implémentation

               

              Maintenant qu’on a vu comment les deux parties indiquent à l’autre leur capacité à signer les flux, il faut qu’ils se mettent d’accord sur le fait de signer les flux. Cette fois-ci, cette décision est faite en fonction du protocole. Ca sera donc décidé d’une certaine manière pour SMBv1, d’une autre pour SMBv2, et d’une autre encore pour LDAP. Mais l’idée reste la même.

              En fonction du protocole, il existe en général 2 voire 3 options pour savoir si les flux seront signés. Les 3 options sont :

                Nous allons voir ici l’exemple de deux protocoles, SMB et LDAP.

                 

                Attaque man in the middle windows NTLM: SMB matrice de signature

                 

                Une matrice est fournie dans la pour savoir si les flux SMB sont signés ou non en fonction des paramètres côté client et côté serveur. Notez cependant que pour SMBv2 et supérieur, la signature est forcément gérée, le paramètre Disabled n’existe plus.

                On note une différence lorsque les deux parties sont en Enabled. En effet, en SMBv1, le paramètre par défaut pour les serveurs était Disabled. Ainsi, tout le traffic SMB entre les clients et les serveurs n’était pas signé. Ca permettait d’éviter de surchager les serveurs en leur évitant de calculer des signatures à chaque envoi de paquet SMB. Comme le statut Disabled n’existe plus pour SMBv2, et que les serveurs sont maintenant en Enabled par défaut, afin de garder ce gain de charge, le comportement entre deux parties Enable a été modifié, et la signature des flux n’est plus mise en place dans ce cas. Il faut nécessairement que le client et/ou le serveur requiert la signature pour que les flux SMB soient signés.

                 

                Paramétrage

                 

                Afin de paramétrer un serveur, il convient de modifier les clés et dans la ruche .

                Cette capture d’écran a été faite sur un contrôleur de domaine. Par défaut, les contrôleurs de domaine requièrent la signature des flux SMB quand un client s’authentifie auprès d’eux. En effet, la GPO appliquée aux contrôleurs de domaine contient cette entrée :

                En revanche, on peut voir sur cette capture qu’au dessus, le même paramètre appliqué à Microsoft network client n’est pas appliqué. Donc lorsque le contrôleur de domaine agit en tant que serveur SMB, les flux doivent être signés, mais si une connexion provient du contrôleur de domaine en direction d’un serveur, cette signature n’est pas requise.

                 

                Mise en place

                 

                Maintenant que l’on sait où se configure la signature des flux SMB, on peut voir ce paramètre appliqué lors d’une connexion. Elle se fait juste avant l’authentification. En fait, lorsqu’un client se connecte au serveur SMB, les étapes sont les suivantes :

                  Voici un exemple de négociation de la signature des flux :

                  On voit une réponse d’un serveur indiquant qu’il possède le paramètre “Enable”, mais qu’il ne requiert pas la signature des flux.

                  Pour résumer, voici comment se déroule une négociation puis une authentification puis une session :

                    Par exemple si un client DESKTOP01 veut communiquer avec un contrôleur de domaine DC01, DESKTOP01 indique qu’il ne requiert pas de signature des flux, mais que cette fonctionnalité est activée.

                    DC01 indique en retour que non seulement la fonctionnalité est activée, mais qu’il la requiert.

                    La phase d’authentification arrive, le client et le serveur mettent le drapeau à 1 puisqu’ils supportent tous les deux la signature des flux.

                    Une fois cette authentification terminée, la session se poursuit, et les échanges SMB sont effectivement signés.

                     

                    Attaque man in the middle windows NTLM: LDAP Matrice de signature

                     

                    Pour LDAP, il y a également trois niveaux :

                      Comme vous pouvez le lire, le niveau intermédiaire, Negociated Signing diffère du cas SMBv2, car cette fois, si le client et le serveur sont en capacité de signer les flux, alors ils le feront. Tandis que pour SMBv2, les flux n’étaient signés que si l’un des deux étaient en niveau Required.

                      Nous avons donc pour LDAP une matrice ressemblant à celle de SMBv1, sauf pour les comportements par défaut.

                      La différence avec SMB est que dans un domaine Active Directory, toutes les machines sont en Negociated Signing. Le contrôleur de domaine n’est pas en Required.

                      Paramétrage

                      Pour le contrôleur de domaine, la clé de registre se trouve dans la ruche et peut valoir 0, 1 ou 2 en fonction du niveau. Elle est à 1 sur le contrôleur de domaine, par défaut.

                      Pour les clients, cette clé se trouve dans la ruche

                      Elle est également à 1 pour les clients. Donc comme nous l’avons vu, comme tous les clients et les contrôleurs de domaine sont en Negociated Signing, tous les flux LDAP sont signés par défaut.

                      Mise en place

                      Contrairement à SMB, il n’y a pas de drapeau dans LDAP qui indique si les flux seront signés ou non. A la place, LDAP utilise les drapeaux positionné dans la négociation NTLM. En effet, il n’y a pas besoin d’avoir plus d’information. Dans le cas ou le client et le serveur supportent la signature LDAP, alors le drapeau sera positionné et les flux seront signés.

                      Si une des deux parties requiert la signature des flux, et que l’autre ne la gère pas, alors tout simplement la session ne débutera pas. Celui qui requiert la signature des flux ignorera les paquets non signés.

                      Nous comprenons alors que, contrairement à SMB, si nous sommes entre un client et un serveur et que nous voulons relayer une authentification vers le serveur en utilisant LDAP, il faut deux choses :

                        Pour le point 2, il arrive que des clients ne positionnent pas ce drapeau, mais malheureusement, le client SMB de Windows le positionne ! Ainsi, en l’état, il n’est pas possible de relayer une authentification SMB vers du LDAP.

                        Et pourquoi pas seulement changer le drapeau à la volée ? Et bien … Les messages NTLM sont également signés. C’est ce que nous allons voir dans le prochain paragraphe.

                         

                        Attaque man in the middle windows NTLM: Signature de l’authentification (MIC)

                         

                        Nous avons vu comment une session pouvait être protégée contre un attaquant en situation d’homme du milieu. Maintenant, pour comprendre l’intérêt de ce chapitre, intéressons-nous à un cas bien particulier.

                        Cas limite

                        Imaginons qu’un attaquant arrive à se mettre en position d’homme du milieu entre un client et un contrôleur de domaine, et qu’il reçoive une demande d’authentification via SMB. Sachant qu’un contrôleur de domaine impose la signature des messages SMB, il n’est pas possible pour l’attaquant de relayer cette authentification via SMB. Il est en revanche possible de changer de protocole, comme nous l’avons vu plus haut, et l’attaquant décide de relayer vers le protocole LDAPS, puisque comme on l’a vu, les données d’authentification sont indépendantes du protocole utilisé.

                        Enfin, presque indépendantes.

                        Presque, parce que nous avons vu que dans les données d’authentification, il y avait le drapeau qui était seulement présent pour indiquer si le client et le serveur supportaient la signature des flux. Et dans certains cas, ce drapeau est pris en compte, comme on l’a vu avec LDAP.

                        Et bien pour LDAPS, ce drapeau est également pris en compte par le serveur. Si un serveur reçoit une demande d’authentification avec le drapeau positionné à 1, il refuse d’authentifier le client. En effet, LDAPS c’est LDAP enrobé (oui j’aime le terme) de TLS, et c’est TLS qui gère la signature (et le chiffrement) des flux. Ainsi, un client LDAPS n’a aucune raison d’indiquer qu’il est en mesure de signer ses flux, et s’il prétend pouvoir le faire, le serveur lui rit au nez et claque la porte.

                        Or dans notre attaque, le client que nous relayons voulait s’authentifier via SMB, donc il indique que oui, il supporte la signature des flux, donc oui, il met le drapeau à 1. Mais si nous relayons son authentification, sans rien modifier, via LDAPS, et bien le serveur LDAPS va voir ce drapeau, et ne va pas nous autoriser à communiquer avec lui.

                        Comme proposé avec le relai de SMB vers LDAP, nous pourrions tout simplement modifier le message NTLM à la volée, et enlever le drapeau. Si nous le pouvions, nous le ferions, et effectivement, ça fonctionnerait bien. Sauf qu’il y a également une signature au niveau NTLM.

                        Cette signature, elle s’appelle le MIC, ou Message Integrity Code.

                         

                        Attaque man in the middle windows NTLM: Le MIC

                         

                        Le MIC, c’est une signature qui est envoyée uniquement dans le dernier message d’une authentification NTLM, le message AUTHENTICATE. Elle prend en compte les 3 messages reçus. Le MIC est calculé avec la fonction HMAC_MD5, en utilisant comme clé un truc qui dépend du secret du client, appelé la clé de session.

                        Ce qui est important, c’est que la clé de session dépend du secret du client. Un attaquant ne peut donc pas re-calculer le MIC.

                        Voilà un exemple de MIC :

                        Du coup, si un seul des 3 messages a été modifié, le MIC ne sera plus valide, puisque la concaténation des 3 messages ne sera pas la même. On ne peut donc pas modifier le drapeau à la volée, comme proposé dans notre exemple.

                        Et si on enlevait juste le MIC ? Parce que oui, le MIC est optionnel.

                        Non, ça ne marchera pas, car il y a un autre drapeau qui indique qu’un MIC sera présent, msAvFlags. Il est présent également dans la réponse et s’il indique 0x00000002, cela signifie au serveur qu’un MIC doit être présent. Donc si le serveur ne voit pas le MIC, il saura qu’il y a baleine sous caillou, et il refusera l’authentification. Si le drapeau dit qu’il doit y avoir un MIC, il doit y avoir un MIC.

                        Très bien, et si jamais on change ce drapeau, on le met à 0, et on enlève le MIC, il se passe quoi ? Comme il n’y a plus de MIC, on ne peut plus vérifier que le message a été modifié ?

                        Et bien, si. Il se trouve que le hash NTLMv2, qui est donc la réponse au challenge envoyé par le serveur, est un hash qui prend en compte non seulement le challenge (évidemment), mais également tous les drapeaux de la réponse. Et vous l’aurez deviné, le drapeau indiquant la présence d’un MIC fait partie de cette réponse.

                        Modifier ou retirer ce drapeau rendrait le hash NTLMv2 invalide, puisque la donnée aura été modifiée. Ce schéma permet de représenter tout ça.

                        Le MIC protège l’intégrité des 3 messages, le drapeau msAvFlags protège la présence du MIC, et le hash NTLMv2 protège la présence du drapeau. L’attaquant, n’ayant pas connaissance du secret de l’utilisateur, ne peut pas recalculer ce hash.

                        Vous l’aurez donc compris, en l’état, nous ne pouvons rien faire dans ce cas là, et ça c’est grâce au MIC.

                         

                        Attaque man in the middle windows NTLM: Drop the MIC

                         

                        Un petit retour sur une vulnérabilité récente trouvée par que vous comprendrez aisément maintenant.

                        C’est la joliement nommée Drop the MIC. Cette vulnérabilité montrait que dans le cas où on ne faisait que retirer le MIC, même si le drapeau indiquait sa présence, le serveur acceptait l’authentification sans broncher. C’était évidemment un bug qui a été corrigé depuis.

                        Elle a été intégrée dans l’outil via l’utilisation du paramètre .

                        Reprenons alors notre exemple de tout à l’heure, mais cette fois avec un contrôleur de domaine encore vulnérable. Voilà ce que ça donne en pratique.

                        Notre attaque fonctionne. Amazing.

                        Pour information, une autre vunérabilité a été trouvée par la même équipe, et s’appelle logiquement

                         

                        Attaque man in the middle windows NTLM: Clé de session

                         

                        Depuis tout à l’heure, nous parlons de signature de la session ou de l’authentification, en disant que pour signer quelque chose, il faut avoir connaissance du secret de l’utilisateur. Nous avons indiqué dans le chapitre sur le MIC qu’en réalité, ce n’est pas exactement le secret de l’utilisateur qui est utilisé, mais une clé appelée clé de session, qui dépend directement du secret de l’utilisateur.

                        Pour vous donner une idée, voici comment est calculée la clé de session pour NTLMv1 et NTLMv2

                        Rentrer dans les explications ne serait pas très utile, mais on voit clairement une différence de complexité d’une version à l’autre. Toute manière je le répète, n’utilisez pas NTLMv1 dans un réseau de production.

                        Avec ces informations, nous comprenons bien que le client peut calculer cette clé de son côté, puisqu’il a toutes les informations en main pour le faire.

                        Le serveur en revanche, ne peut pas toujours faire ça tout seul, comme un grand. Dans le cas d’une , il n’y a pas de problème puisque le serveur connait le hash NT de l’utilisateur.

                        En revanche lors d’une , le serveur va devoir demander au contrôleur de domaine de calculer cette clé de session à sa place, et de la lui renvoyer. Nous avons vu dans l’article sur pass-the-hash que le serveur envoie une demande au contrôleur de domaine dans une structure et que le contrôleur de domaine répond avec une structure . C’est dans cette réponse du contrôleur de domaine que se trouve la clé de session, en cas d’authentification réussie.

                        La question qui se pose alors, c’est de savoir ce qui empêche un attaquant de faire la même demande que le serveur cible auprès du contrôleur de domaine. Et bien avant la , rien !

                        What we found while implementing the NETLOGON protocol [12] is the domain controller not verifying whether the authentication information being sent, was actually meant to the domain-joined machine that is requesting this operation (e.g. NetrLogonSamLogonWithFlags()). What this means is that any domain-joined machine can verify any pass-through authentication against the domain controller, and to get the base key for cryptographic operations for any session within the domain.

                        Donc évidemment, Microsoft a corrigé ce bug. Pour vérifier que seul le serveur sur lequel s’authentifie l’utilisateur a le droit de demander la clé de session, le contrôleur de domaine va vérifier que la machine cible présente dans la réponse est la même que la machine effectuant la requête NetLogon.

                        Dans la réponse , nous avons vu la présence d’un drapeau indiquant la présence ou non du MIC, mais il y a également d’autres informations, telle que le nom Netbios de la machine cible de l’authentification.

                        C’est ce nom là qui est comparé avec la machine effectuant la requête NetLogon. Ainsi, si l’attaquant essaie de faire une requête NetLogon pour avoir la clé de session, le nom de l’attaquant ne correspondant pas au nom de la machine dans la réponse NTLM, le contrôleur de domaine va rejeter la demande.

                        Enfin, de la même manière que , nous ne pouvons pas modifier le nom de la machine à la volée dans la réponse NTLM, car il est pris en compte dans le calcul de la réponse NTLMv2.

                        Une vulnérabilité similaire a été découverte récemment par l’équipe de Preempt drop the mic 2.

                         

                        Attaque man in the middle windows NTLM: Channel Binding

                         

                        Nous allons parler d’une dernière notion. Plusieurs fois nous avons répété que la couche d’authentification, donc les messages NTLM, était quasi-indépendante de la couche applicative, du protocole utilisé (SMB, LDAP, …). Je dis “quasi” parce que nous avons vu que certains protocoles utilisent les drapeaux des messages NTLM pour savoir si la session doit être signée ou non.

                        Quoiqu’il en soit, en l’état, il est tout à fait possible pour un attaquant de récupérer un message NTLM dans un protocole A, et de le renvoyer dans un protocole B. C’est le principe du relai cross-protocole que nous avons déjà évoqué.

                        Et bien une nouvelle protection existe pour contrer cette attaque. C’est la protection appelée channel binding, ou liaison de canaux, en bon français. Le principe de cette protection, c’est de lier la couche authentification avec le protocole utilisé, voire avec la couche TLS dans laquelle tout est parfois encapsulé (LDAPS ou HTTPS par exemple). L’idée générale étant que dans le dernier message NTLM , il y ait une information non modifiable par un attaquant qui indique le service souhaité, et potentiellement une autre information qui contienne une emprunte du certificat du serveur avec qui elle communique.

                        Nous allons voir ces deux principes un peu plus en détail, mais ne vous inquiétez pas, c’est relativement simple à comprendre.

                         

                        Liaison avec le service

                         

                        Cette première protection est assez simple à comprendre. Si un client souhaite s’authentifier auprès d’un serveur pour utiliser un service spécifique, l’information identifiant le service sera ajoutée dans la reponse NTLM.

                        De cette manière, lorsque le serveur légitime reçoit cette authentification, il peut voir le service qui a été demandé par le client, et s’il diffère de ce qui est vraiment demandé, il n’accepte pas de fournir le service.

                        Le nom du service se trouvant dans la réponse NTLM, il est protégé par la réponse NtProofStr qui est un HMAC_MD5 de cette information, du challenge, et d’autres informations comme le msAvFlags. Elle est, je le rappelle, calculée avec le secret du client.

                        Dans l’exemple présenté dans le dernier schéma, nous voyons un client qui tente de s’authentifier via HTTP auprès du serveur. Sauf que le serveur, c’est un attaquant, et l’attaquant rejoue cette authentification auprès du serveur légitime, pour accéder non plus à un service web (via HTTP), mais un partage réseau (SMB).

                        Sauf que le client a indiqué le service qu’il souhaitait utiliser dans sa réponse NTLM, et comme l’attaquant ne peut pas le modifier, il est obligé de le relayer tel quel. Le serveur reçoit alors le dernier message, compare le service demandé demandé par l’attaquant avec le service renseigné dans le message NTLM, et refuse la connexion en s’apercevant que les deux services ne correspondent pas.

                        Concrètement, ce qu’on appelle service, c’est en fait le SPN ou Service Principal Name qui est renseigné dans le dernier message NTLM. J’ai consacré à l’explication de cette notion, je vous invite à vous y réferrer si nécessaire.

                        Voilà une capture d’écran d’un client qui envoie le SPN dans sa réponse NTLM.

                        Nous voyons qu’il indique bien vouloir utiliser le service CIFS (équivalent de SMB, juste une différentes terminologie). Relayer ça vers un serveur LDAP qui prend en compte cette information résultera en un beau refus de la part du serveur.

                        Mais comme vous pouvez le voir, il n’y a pas que le nom du service dans le SPN (CIFS). Il y a également la cible de l’authentification, ici l’adresse IP de l’attaquant. Cela implique que si un attaquant relaie ce message à un serveur, et que le serveur vérifie le SPN, il verra qu’il n’est pas destination indiquée dans le SPN et refusera la connexion.

                        Ainsi, cette protection, si supportée par tous les clients et serveurs, et si requise pour tous les serveurs, protège de tout relai NTLM.

                         

                        Attaque man in the middle windows NTLM: Liaison avec la couche TLS

                         

                        Cette fois-ci, cette protection a pour but de lier la couche d’authentification, donc toujours les messages NTLM, à la couche TLS qui peut potentiellement être utilisée.

                        Si le client souhaite utiliser un protocole encapsulé dans TLS (HTTPS, LDAPS par exemple), il va établir une session TLS avec le serveur, et il va créer un condensat du certificat du serveur qu’il va mettre dans sa réponse NTLM. Ce condensat est appéle Channel Binding Token, ou CBT. Le serveur légitime va alors recevoir le message NTLM à la fin de l’authentification, lire le condensat indiqué dans la réponse, et le comparer avec le vrai condensat de son certificat. S’il est différent, c’est qu’il n’est pas le destinataire original de cet échange.

                        Encore une fois, ce condensat se trouvant dans la réponse NTLM, il est protégé par la réponse NtProofStr, comme pour le SPN du Service Binding.

                        De cette manière, les deux attaques suivantes ne sont plus possibles :

                          Voilà un schéma un peu barbu pour représenter le 2ème cas.

                          Il montre l’établissement de deux sessions TLS. L’une entre le client et l’attaquant (en rouge) et une entre l’attaquant et le serveur (en bleu). Le client va récupérer le certificat de l’attaquant, et en calculer un condensat, cert hash, en rouge.

                          A la fin des échanges NTLM, ce condensat sera mis dans la réponse NTLM, et sera protégée puisqu’il fait partie de la donnée chiffrée de la réponse NTLM. Quand le serveur recevra ce condensat, il va calculer le condensat de son propre certificat, et en voyant que ce n’est pas le même, il refusera la connexion.

                          Encore une fois, Preempt a récemment qui a depuis été corrigée à ce sujet.

                           

                          Attaque man in the middle windows NTLM: Que peut-on relayer ?

                           

                          Avec toutes ces informations, vous devriez être capables de savoir les quels protocoles peuvent être relayés vers quels protocoles. Nous avons vu qu’il était impossible de relayer du SMB vers du LDAP ou du LDAPS, par exemple. En revanche, tout client qui ne positionne pas le drapeau peut être relayé vers LDAP si la signature n’est pas imposée, ou LDAPS si le channel binding n’est pas requis.

                          Comme il existe beaucoup de cas, voici un tableau qui en résume certains.

                          Concernant LDAPS ou HTTPS en client, je les ai mis dans le tableau, sous réserve que la CA qui a généré le certificat de l’attaquant soit acceptée par le client. Par ailleurs, d’autres protocoles pourraient être ajoutés, comme SQL ou SMTP, mais j’avoue ne pas avoir lu la documentations de tous les protocoles de la planète.

                          Pour les cases grises, je ne sais pas comment réagit un serveur HTTPS lorsqu’il reçoit une authentification avec le drapeau à 1

                          .

                          Attaque man in the middle windows NTLM: Bannir  NTLMv1!

                           

                          J’ajoute un petit fun fact que m’a suggéré d’ajouter , c’est que comme on l’a vu, le hash NTLMv2 d’un client prend en compte le challenge du serveur, mais aussi notamment le drapeau qui indique la présence ou non d’un MIC, ou le champ indiquant le nom de la machine cible lors de l’authentification, ou encore le SPN ou le CBT pour le channel binding.

                          Et bien le protocole NTLMv1 ne fait pas ça. Il ne prend en compte que le challenge du serveur. En fait, il n’y a plus les informations complémentaires comme le nom de la cible, le drapeau , le SPN ou le CBT.

                          Ainsi, si une authentification NTLMv1 est autorisée par un serveur, l’attaquant peut simplement enlever le MIC et ainsi relayer des authentifications vers LDAP ou LDAPS, par exemple. Mais il peut aussi (et surtout) effectuer des requêtes NetLogon pour récupérer la clé de session. En effet, le contrôleur de domaine n’a aucun moyen de vérifier si l’attaquant a le droit, ou non, de faire cette demande. Et comme il ne va pas bloquer un parc de production qui ne serait pas complètement à jour, et bien il va gentiment la donner, pour des “raisons de rétro-compatibilité”.

                          Une fois en possession de la clé de session, l’attaquant peut alors signer tous les paquets qu’il souhaite. Ainsi, il peut même discuter avec les machines qui requièrent la signature des flux.

                          C’est le comportement “by design” donc ça ne peut pas être corrigé. Donc je le répète, n’autorisez pas NTLMv1 dans un réseau de production.

                           

                          Conclusion

                           

                           

                          Nous avons vu ici le fonctionnement du relai NTLM, en prenant bien conscience que l’authentification et la session qui s’en suit sont deux notions distinctes permettant de faire du relai cross-protocole dans beaucoup de cas. Bien que le protocole englobe d’une manière ou d’une autre les données d’authentification, elles sont pour lui opaques, et gérées par SSPI.

                          Nous avons également montré en quoi la signature des flux pouvait protéger le serveur d’attaques de type homme du milieu. Pour cela, la cible doit attendre une signature des flux de la part du client, sinon l’attaquant pourra se faire passer pour quelqu’un d’autre sans avoir à signer les messages qu’il envoie.

                          Nous avons vu que le MIC était très important pour protéger les échanges NTLM, notamment le drapeau indiquant si les flux seront signés pour certains protocoles, ou les informations sur le channel binding.

                          Nous avons d’ailleurs terminé en montrant comment le channel binding permettait de faire le lien entre la couche d’authentification et la couche de session, soit via le nom du service, soit via une liaison avec le certificat du serveur.

                          J’espère que ce long article vous a permis de mieux comprendre ce qu’il se passait lors d’une attaque de relai NTLM. Vous comprenez j’espère mieux les briques qui entrent en jeu, et les protections existantes.

                           

                           

                           

                          Il faut donc éviter d'utiliser NTLMV1.

                           

                            

                          Cet article reflète exclusivement l'opinion de ses auteurs et n’engage en aucune façon Consultingit. J'espère que ça vous a plu. Vos commentaires/remarques sont les bienvenus: