Première rédaction de cet article le 29 juillet 2009
La mise à jour, lors d'urgences frénétiques, de logiciels critiques, est une occupation courante sur l'Internet. Aujourd'hui, c'est BIND, un habitué de ce genre de distractions, qui nous offre une telle émotion, avec la faille de sécurité CVE-2009-0696, alias VU#725188, la possibilité de planter BIND à distance par le biais d'une requête DNS de mise à jour dynamique, même si la configuration du serveur n'autorise pas de telles mises à jour.
Annoncée le 28 juillet par
l'ISC, cette faille, spécifique à BIND (contrairement à la
faille Kaminsky), vient
d'une mauvaise analyse des requêtes de mise à jour dynamique
(dynamic update, normalisé dans le RFC 2136). Lorsqu'il reçoit une requête DNS spécialement
fabriquée, où le pré-requis à la mise à jour, dans le paquet, a
le type ANY
(normalement jamais utilisé), le
serveur plante immédiatement et écrit dans son
journal :
Jul 29 09:10:57 lilith named[2428]: db.c:619: \ REQUIRE(type != ((dns_rdatatype_t)dns_rdatatype_any)) failed Jul 29 09:10:57 lilith named[2428]: exiting (due to assertion failure)
(On note que l'adresse IP de l'attaquant n'apparait pas dans ce message et que, de toute façon, un seul paquet UDP suffit et que son adresse source peut être mensongère.) Il n'y a plus qu'à redémarrer BIND et, entre temps, on n'a pas de résolution de noms. Si le domaine n'utilise que BIND (ce qui est hélas courant) et que l'attaquant vise tous les serveurs du domaine, il peut faire disparaitre le domaine de l'Internet. C'est d'ailleurs en raison de ce genre de risques qu'il faut que les serveurs Internet soient de diverses origines. Par exemple, il ne faut pas utiliser que BIND, il est important d'avoir également d'autres logiciels comme NSD.
Pour que le serveur soit vulnérable, il faut aussi qu'il fasse
autorité pour au
moins une zone DNS de type master
(slave
ne suffit pas). Comme BIND, par défaut,
est master
pour localhost
et
0.0.127.in-addr.arpa
, cela explique que la grande
majorité des serveurs BIND sont vulnérables.
L'exploitation de cette faille a été rendue publique et peut-être
aussi simple que ce programme écrit
en Perl. Voici, vue par
tshark, le paquet d'attaque
(utilisant la zone localhost
pour laquelle tous
les BIND font autorité par défaut) :
Domain Name System (query) Transaction ID: 0x6142 Flags: 0x2800 (Dynamic update) 0... .... .... .... = Response: Message is a query .010 1... .... .... = Opcode: Dynamic update (5) .... ..0. .... .... = Truncated: Message is not truncated .... ...0 .... .... = Recursion desired: Don't do query recursively .... .... .0.. .... = Z: reserved (0) .... .... ...0 .... = Non-authenticated data OK: Non-authenticated data is unacceptable Zones: 1 Prerequisites: 1 Updates: 1 Additional RRs: 0 Zone localhost: type SOA, class IN Name: localhost Type: SOA (Start of zone of authority) Class: IN (0x0001) Prerequisites localhost: type ANY, class IN Name: localhost Type: ANY (Request for all records) Class: IN (0x0001) Time to live: 0 time Data length: 0 Updates localhost: type ANY, class ANY Name: localhost Type: ANY (Request for all records) Class: ANY (0x00ff) Time to live: 0 time Data length: 0
On peut examiner le paquet complet sur pcapr.net.
La solution la plus propre est de mettre à jour BIND vers une version sûre, et d'urgence, en suivant la liste donnée par l'ISC. Avec les versions officielles de l'ISC, vous pouvez voir si un serveur est à jour avec :
% dig @ns1.EXAMPLE.net CH TXT version.bind.
et vous obtenez le numéro de version que vous pouvez comparer à la liste des versions sûres. Attention : avec beaucoup de paquetages BIND de différents systèmes d'exploitation, le numéro de version n'est pas forcément modifié lors de l'application de mises à jour de sécurité.
Si cette mise à jour est
difficile, pour une raison ou pour une autre,
le plus simple est de « démasteriser », c'est-à-dire de supprimer les
zones de type master
de la configuration
(named.conf
). Sur un serveur qui est uniquement à
autorité, cela n'est pas un problème. Sur un serveur récursif, cela
entrainera quelques disfonctionnements mais qui ne sont probablement
pas trop graves, par rapport aux risques de la faille.
Une des raisons pour lesquelles on n'a pas toujours la possibilité de faire une mise à jour est que les fournisseurs réagissent plus ou moins rapidement. À l'heure où j'écris, Debian a fait une mise à jour mais pas RHEL, pourtant bien plus cher.
Une dernière solution pour protéger votre serveur est de demander au pare-feu, si vous n'utilisez pas les mises à jour dynamiques, de les bloquer. Avec Netfilter, on peut bloquer une partie de ces requêtes et donc les attaques du script cité plus haut avec :
iptables -A INPUT -p udp --dport 53 -j DROP -m u32 --u32 '30>>27&0xF=5'
Mais cela n'empêche pas tout : comme le filtre ci-dessus travaille avec des offsets fixes, il peut être contourné, par exemple, si l'attaquant rajoute des options dans le paquet. (La difficulté à écrire des règles u32 pour le DNS a été abordée dans un autre article.)
Si vous voulez capturer les requêtes DNS de mise à jour dynamique, pour analyse ultérieure, et que vous utiliser dnscap, une requête comme :
# dnscap -w updates -mu -i eth0
conviendra (-mu
ne garde que les requêtes
d'opcode UPDATE
). Si vous
voulez juste les voir et pas les enregistrer sur disque, remplacez
-w updates
par -g
.
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)