Je suis Charlie

Autres trucs

Accueil

Seulement les RFC

Seulement les fiches de lecture

Mon livre « Cyberstructure »

Ève

Comment fonctionne la faille DNS « Kaminsky » ?

Première rédaction de cet article le 31 juillet 2008


La faille de sécurité DNS découverte par Dan Kaminsky à l'hiver 2007-2008 et annoncée le 8 juillet 2008 n'a pas encore été officiellement publiée en détail. Cela doit être fait le 8 août à la conférence BlackHat à Las Vegas. Mais, l'Internet étant ce qu'il est, il n'est pas étonnant que cette date n'aie pas été tenue et que les informations aient été publiées avant l'annonce officielle. Trois exploitations de la faille ont déjà été publiées. Plusieurs articles publics ont déjà repris en détail ces informations (voir par exemple, en français, l'article de Sid. On peut donc désormais expliquer en quoi cette faille consiste.

Je tiens d'abord à rappeler que des tas de bêtises ont été écrites sur l'Internet (et plus encore dans la presse papier ou à la télévision) sur cette faille. Ne vous fiez pas à des messages arrogants d'ignorants complets qui écrivent dans les commentaires d'un blog « La faille est une faiblesse du générateur aléatoire de BIND » ou bien « C'est une faille classique et il n'y a rien de nouveau ».

Plaçons un peu de contexte : le DNS fonctionne typiquement sur UDP (il peut aussi utiliser TCP et l'utilisation de ce protocole règlerait complètement la faille Kaminsky mais beaucoup de serveurs de noms sont incorrectement configurés et refusent les accès TCP). UDP n'a pas la notion de connexion et l'adresse IP de la machine avec laquelle on parle n'est donc pas du tout authentifée (avec TCP, elle est vérifiée par le processus de connexion, le 3-way handshake - section 3.4 du RFC 793 -, ainsi que par les numéros de séquence, qui doivent démarrer d'un nombre imprévisible). Lorsqu'un résolveur (le serveur de noms qui pose une question) interroge le serveur faisant autorité (le serveur de noms qui connait la réponse), il ne peut pas savoir si la réponse vient bien du serveur faisant autorité, elle peut venir d'un méchant qui a usurpé l'adresse IP de celui-ci, et répondu avant lui. Si le méchant peut donc deviner quant une requête va être émise (il existe des techniques pour cela, la plus simple étant de la générer soi-même, si le résolveur est un récursif ouvert, ou bien si on dispose d'un zombie autorisé à y accéder), cet attaquant peut envoyer une fausse réponse (en bombardant le vrai serveur en même temps, le méchant peut le ralentir pour augmenter les chances de gagner la course).

S'il n'y avait que cela, le DNS serait trivial à abuser. Mais quelques protections existent : la plus importante est que la requête DNS contient un nombre, le Query ID (QID, parfois appelé Transaction ID, TXID). Il est décrit dans la section 4.1.1 du RFC 1035. Le résolveur n'accepte une réponse que si elle contient un Query ID identique à celui qu'il a lui-même envoyé. La réponse doit également correspondre à une question actuellement en suspens et être reçue sur le port UDP d'où venait la question. (Il y a très longtemps, les implémentations du DNS étaient naïves et acceptaient à peu près n'importe quoi, ce qui est fini depuis belle lurette.) Malheureusement, le Query ID ne fait que 16 bits de long, ce qui est suffisant pour démêler des questions distinctes mais pas assez pour sécuriser la transaction. Envoyer 2^16 soit 65 536 réponses fausses pour qu'au moins une soit acceptée ne prend pas assez de temps, avec l'Internet rapide d'aujourd'hui. (Une vraie solution à la faille Kaminsky et à toutes les failles de la même famille serait de passer le Query ID à 128 bits. Mais cela serait un changement du DNS incompatible.)

Cette faiblesse du DNS est connu depuis très longtemps. Par exemple, en 1995, Paul Vixie écrivait « With only 16 bits worth of query ID and 16 bits worth of UDP port number, it's hard not to be predictable. A determined attacker can try all the numbers in a very short time and can use patterns derived from examination of the freely available BIND code. Even if we had a white noise generator to help randomize our numbers, it's just too easy to try them all. ». Ce risque (et d'autres) a été documenté par exemple dans le RFC 3833 en 2004. Il n'y a en effet rien de nouveau ici, mais la faille Kaminsky permet d'exploiter cette vulnérabilité avec bien plus d'efficacité qu'une attaque par force brute.

Jusqu'à présent, en effet, cette protection avait quand même suffit, à condition que le Query ID soit réellement aléatoire (suivant les recommandations du RFC 4086). Des problèmes étaient survenus avec le serveur DNS de Microsoft (qui n'utilisait que 14 des 16 bits du Query ID) ou avec BIND (générateur aléatoire bogué, faille CVE-2007-2926). Mais ils étaient facilement solubles en mettant à jour le logiciel bogué.

Fin 2007, la situation était donc d'une faiblesse connue (16 bits ne sont pas suffisants) mais peu exploitée car l'attaque n'était pas pratique. Typiquement, si on voulait empoisonner le cache d'un résolveur pour le nom www.example.com, il fallait d'abord attendre l'expiration de l'enregistrement stocké (si on a accès au résolveur, c'est facile, puisque le TTL est publié), faire en sorte qu'une question sur www.example.com soit générée (là encore, c'est beaucoup plus facile si on a accès au résolveur) et, pendant les quelques dizaines de millisecondes avant que les serveurs faisant autorité répondent, envoyer une bouffée de fausses réponses, en comptant qu'une corresponde. Même aidé par le paradoxe de l'anniversaire, cela ratait plus souvent que cela ne réussissait.

La menace se rapprochait toutefois suffisamment pour avoir poussé l'IETF à s'intéresser au travail de Bert Hubert sur la résistance aux faux. Ce travail est actuellement documenté dans l'Internet-Draft Measures for making DNS more resilient against forged answers. Ce document, pas encore approuvé, contient de très intéressants calculs quantitatifs sur l'attaque exposée ci-dessus, évaluant ses chances de succès (trop élevées, hélas) et proposant des mesures pour rendre l'attaque plus difficile, mesures dont la principale est la SPR (Source Port Randomisation, le fait de rendre le port UDP source imprévisible, le faisant ainsi venir au secours du Query ID). Ce travail avançait cahin-caha lorsque la nouvelle de la faille Kaminsky a commencé à circuler en février 2008.

Cette faille est très simple dans son principe. Elle repose sur la faiblesse expliquée ci-dessus (les 16 bits du Query ID ne représentent pas suffisamment d'entropie). Mais elle la rend facilement exploitable. Avant Kaminsky, toutes les attaques reposaient sur une question portant sur le nom qu'on voulait détourner. Si on voulait empoisonner le cache avec une fausse valeur pour www.example.com, on faisait poser au résolveur la question « Quelle est l'adresse IP de www.example.com ? » et on glissait une fausse réponse. Le problème de cette méthode est qu'on n'a droit qu'un un essai : même s'il reçoit plusieurs questions identiques de ses clients, le résolveur n'en envoie qu'une seule et il faut donc deviner le Query ID de cette unique question. Pire, si on rate son coup, la bonne réponse, celle qui vient du serveur faisant autorité, va être mise dans le cache du résolveur et, si le TTL a une valeur raisonnable, l'attaquant ne pourra pas réessayer avant plusieurs heures ou même jours.

Dan Kaminsky a innové essentiellement sur un point : si on veut fausser www.example.com, on va demander au résolveur des informations sur quelquechoseNNN.example.com où NNN est un nombre qui varie à chaque requête. Ainsi, le résolveur devra envoyer autant de requêtes que de noms de domaine différents, augmentant énormément les chances de l'attaquant, surtout s'il est aidé par le paradoxe de l'anniversaire. Notez que, le nom de la zone (ici example.com) doit être le même, pour que les requêtes aillent toutes au même serveur faisant autorité mais aussi pour passer les contrôles du paragraphe suivant.

Bon, maintenant, l'attaquant, au lieu de n'avoir qu'une seule chance, en a des milliers et l'attaque devient bien plus facile. Mais quel intérêt pour lui d'arriver à mettre une fausse réponse pour quelquechose5447.example.com dans le cache du résolveur ? C'était www.example.com qui l'intéressait ! C'est la deuxième innovation de Kaminsky. Dans la fausse réponse, l'attaquant glisse non seulement un enregistrement pour quelquechoseNNN.example.com (qui n'est pas obligatoire, on peut aussi répondre sans section Answer) mais également des enregistrements pour www.example.com dans les autres sections comme Additional. Les tests qu'effectuent les résolveurs ne suffiront pas à le rejeter puisque ce nom est dans le bailliage (les résolveurs rejettent les noms dits « hors-bailliage », les noms qui sont dans une autre zone que la zone du nom cherché, justement pour limiter les risques d'empoisonnement).

Si jamais le résolveur devenait davantage paranoïaque, il suffirait d'ailleurs de glisser de faux enregistrements NS (Name Server) et une fausse colle dans la section Authority, que le résolveur ne peut pas ignorer. C'est ce que fait une des exploitations, et voici la réponse DNS fausse, telle que vue par Wireshark. Ici, on a tenté de tricher sur l'adresse IP de www.example.com, un domaine dont les serveurs faisant autorité sont à l'IANA (ici, 193.0.0.236). On tente d'empoisonner le cache avec l'adresse 192.0.2.1 :

...
    Source: 193.0.0.236 (193.0.0.236)
    Destination: 192.0.2.253 (192.0.2.253)
User Datagram Protocol, Src Port: 53 (53), Dst Port: 49186 (49186)
    Source port: 53 (53)
    Destination port: 49186 (49186)
    Length: 175
    Checksum: 0x98a1 [correct]
        [Good Checksum: True]
        [Bad Checksum: False]
Domain Name System (response)
    Transaction ID: 0x0001
    Flags: 0x8400 (Standard query response, No error)
        1... .... .... .... = Response: Message is a response
        .000 0... .... .... = Opcode: Standard query (0)
        .... .1.. .... .... = Authoritative: Server is an authority for domain
        .... ..0. .... .... = Truncated: Message is not truncated
        .... ...0 .... .... = Recursion desired: Don't do query recursively
        .... .... 0... .... = Recursion available: Server can't do recursive queries
        .... .... .0.. .... = Z: reserved (0)
        .... .... ..0. .... = Answer authenticated: Answer/authority portion was not authenticated by the server
        .... .... .... 0000 = Reply code: No error (0)
    Questions: 1
    Answer RRs: 1
    Authority RRs: 1
    Additional RRs: 1
    Queries
        deb623f600000009.example.com: type A, class IN
            Name: deb623f600000009.example.com
            Type: A (Host address)
            Class: IN (0x0001)
    Answers
        deb623f600000009.example.com: type A, class IN, addr 1.1.1.1
            Name: deb623f600000009.example.com
            Type: A (Host address)
            Class: IN (0x0001)
            Time to live: 1 day
            Data length: 4
            Addr: 1.1.1.1
    Authoritative nameservers
        example.com: type NS, class IN, ns www.example.com
            Name: example.com
            Type: NS (Authoritative name server)
            Class: IN (0x0001)
            Time to live: 1 day
            Data length: 20
            Name server: www.example.com
    Additional records
        www.example.com: type A, class IN, addr 192.0.2.1
            Name: www.example.com
            Type: A (Host address)
            Class: IN (0x0001)
            Time to live: 1 day
            Data length: 4
            Addr: 192.0.2.1

L'attaque Kaminsky est donc bien nouvelle. Elle passe d'une méthode laborieuse et ayant de faibles chances de succès à une méthode qui marche à presque tous les coups et en très peu de temps (moins de dix minutes avec les exploitations publiées, beaucoup moins avec certaines non publiées).

Voici pourquoi il est donc urgent de mettre à jour, si ce n'est pas encore fait, les résolveurs DNS dont vous avez la responsabilité. À part PowerDNS et Unbound, qui le mettaient déjà en œuvre, cette mise à jour installe la SPR (rendre le port source aléatoire) sur les résolveurs. On passe ainsi de seulement 16 bits d'entropie (le Query ID) à 32 (le Query ID plus le port source, qui est également sur 16 bits). Cela retarde le moment où l'attaque sera efficace, en attendant des mesures plus radicales.

Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)

Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)