Journal Faille de sécurité dans la GNU libc avec les requêtes DNS

Posté par  (site web personnel, Mastodon) . Licence CC By‑SA.
54
17
fév.
2016

Une faille très sérieuse (CVE-2015-7547) vient d'être découverte dans la GNU libc (qui équipe tous les serveurs et desktops utilisant Linux…). Lorsqu'on résoud un nom en adresse, avec getaddrinfo(), le tampon où arrive la réponse n'est pas toujours le bon, et une réponse de grande taille peut écraser la mémoire, et mener au crash du client, voire à l'exécution de code (aïe).

Une exploitation typique est : le méchant se connecte à un serveur SMTP GNU/Linux depuis une adresse IP dont il contrôle in-addr.arpa et/ou ip6.arpa (les domaines qui servent aux résolutions d'adresses IP en noms). Le serveur SMTP fait des requêtes DNS (PTR puis A et AAAA). La réponse (contrôlée par l'attaquant) est de grande taille et paf (le chien).

Il est donc essentiel de mettre à jour tout de suite.

À noter que l'équipe de la glibc donne des conseils stupides (limiter la taille des réponses DNS, par exemple dans un pare-feu, débrayer IPv6 et/ou DNSSEC dans les applications) qui ramèneraient quinze ans en arrière.

  • # Euh....

    Posté par  . Évalué à 10.

    À noter que l'équipe de la glibc donne des conseils stupides (limiter la taille des réponses DNS, par exemple dans un pare-feu, débrayer IPv6 et/ou DNSSEC dans les applications) qui ramèneraient quinze ans en arrière.

    Ca n'a rien de stupide, au contraire.
    Si tu as un parc de 800 serveurs à mettre à jour, ce genre de limitations que tu peux mettre en place en amont peut t'éviter de te faire trouer en attendant que tu fasses l'update de tes machines… car, pour peu que tu sois sur des OS un peu customisé, la mise à jour de libc peut être cause de suée …

    • [^] # Re: Euh....

      Posté par  (site web personnel, Mastodon) . Évalué à 10.

      Débrancher les machines marcherait aussi… Ces conseils stupides vont avoir des conséquences : plus de connexion IPv6, plus de sécurité (en coupant DNSSEC et en limitant la taille).

      Donc, oui, c'est stupide et il est regrettable que des publications comme Hacker News http://thehackernews.com/2016/02/glibc-linux-flaw.html aient repris ce conseil de manière acritique.

      Par ailleurs, si on a un parc de 800 machines, et aucun mécanisme pour les mettre à jour, on est de toute façon mal parti…

      • [^] # Re: Euh....

        Posté par  (site web personnel) . Évalué à 8.

        Je pense que ce serait une erreur d'appliquer ces recommandations a la lettre et pour tous les cas existants, tout autant qu'il serait stupide de les rejeter en bloc.
        Nous n'avons pas tous les memes cas d'usage. Entre Mr Michu (oui, madame delegue a son mari parfois) qui a son serveur perso sur internet (ben oui, il a decouvert Linux, c'est cool, mais le firewall j'ai rien compris, alors j'ai ouvert tous les ports sur ma CoincoinBOX) et des fermes de serveurs critiques niveau business accessibles sur Internet il faut je pense faire la part des choses.

        • [^] # Re: Euh....

          Posté par  . Évalué à 2.

          mais le firewall j'ai rien compris, alors j'ai ouvert tous les ports sur ma CoincoinBOX

          J’aimerais qu’on m’explique un jour les raisons derrière ce fétichisme de « il faut fermer tous les ports même s’il y a rien qui écoute derrière ».

          Sur mon VPS perso j’ai 0 ports fermés et j’ai du mal à voir où est le problème.

          • [^] # Re: Euh....

            Posté par  (site web personnel) . Évalué à 1.

            Sur un serveur tu installes tout et n'importe quoi comme une grande partie des gens ont tendance a le faire sur un desktop ?

            • [^] # Re: Euh....

              Posté par  . Évalué à 3.

              Justement non, je fais gaffe à ce que j’installe, du coup je ne me retrouve pas avec des services inconnus qui écoutent sur des ports dont je n’ai pas besoin. Les ports ouverts sont ceux dont j’ai besoin, les autres sont fermés pour la bonne et simple raison que personne n’écoute derrière, pas par un firewall dont je ne vois pas l’utilité.

              • [^] # Re: Euh....

                Posté par  . Évalué à 10.

                Imagine que un attaquant arrive a exécuter un code sur ton serveur qui lance un programme communiquant avec l'extérieur. Avec un parefeu ou tous les ports sont bloqué le programme n'aura qu'une portée très limité voir nulle, avec tous les port ouvert il n'aura aucun mal a faire ses méfaits …
                Exemple concret une faille d'un site web permet a un pirate de lancer un relai de spam, avec un pare-feu restrictif = 0 spam envoyé, si ouvert = Bannissement de tes IP même pour ton serveur de mail légitime.

                • [^] # Re: Euh....

                  Posté par  . Évalué à 8.

                  Tout à fait …
                  Je rajouterai que, si l'on veut bien faire, il faut filtrer en entrée ET en sortie.

                  Perso, au boulot, j'administre une infra un peu critique (hébergement de code très sensible sous NDA qui, s'il fuitait, nous exposerait à des lourdes poursuites) et je filtre même l'HTTP en sortie.

                  Car en admettant que tu filtres les ports en écoute, les pirates ont la parade avec les shellcode qui font du connect back … donc il faut tout filtrer.

                  Encore une fois, il faut bien garder en tête que la sécurité à appliquer à un système doit rester fonction des données à protéger…

          • [^] # Re: Euh....

            Posté par  (Mastodon) . Évalué à 10.

            Prophylaxie, défense en profondeur, même si tu gère bien ton serveur, tu n’est pas à l’abri d’une mise à jour ou lors d’une installation d’avoir une appli qui écoute sur un port non prévu. Si tu te fait trouer une appli sans élévation de privilège, ça évite de rendre des services non désirés.
            Une fois le pare feux en place, ça permet facilement de virer les « méchants » (fail2ban, snort/suricata + ipset…).
            Ça à pour effet de bord de ralentir les scanners de ports (DROP plutôt qu’un ICMP port unreachable), donc c’est bénéfique pour tout le monde ☺

            • [^] # Re: Euh....

              Posté par  (site web personnel) . Évalué à 3.

              +1

              Tu bloques une éventuelle backdoor via le firewall qui rend inacessible celle ci sur le serveur web par exemple.

              Système - Réseau - Sécurité Open Source

    • [^] # Re: Euh....

      Posté par  (site web personnel, Mastodon) . Évalué à 10.

      Personne n’a suggéré de simplement désinstaller la glibc ?
      Les trolls, c’est plus ce que c’était…

  • # Dans la presse généraliste

    Posté par  (site web personnel, Mastodon) . Évalué à 7.

    Un mauvais article de la BBC (la grande majorité des objets, de l'embarqué, n'utilise pas la glibc) http://www.bbc.com/news/technology-35592916 et un autre d'Ars Technica (qui reprend les mauvais conseils des mainteneurs de la glibc) http://arstechnica.com/security/2016/02/extremely-severe-bug-leaves-dizzying-number-of-apps-and-devices-vulnerable/

  • # IPv6

    Posté par  (Mastodon) . Évalué à 5.

    D’après, le rapport de bogue pointé, la désactivation d’IPv6 (à quelque niveau que ce soit, OS, résolveur cache…) ne fait pas partie des solutions applicables, ça n’empêchera pas les applications (donc la libc) de faire des requêtes de type AF_UNSPEC (donc demander en // un A et un AAAA), l’exploit pouvant se trouver dans la réponse A, même s’il n’y a pas de réponse AAAA.

  • # Pour tester

    Posté par  (site web personnel, Mastodon) . Évalué à 5.

    Si vous voulez crasher vos logiciels utilisant la vieille libc, voici un service utile :

    http://5.150.196.47/

  • # Pour parer au plus pressé…

    Posté par  . Évalué à 8.

    Il y a toujours la solution expliquée ici ;-)

  • # Debian

    Posté par  . Évalué à 10.

    Pour information, la mise à jour est passée dans Debian stable et sid. Les versions de la glibc qui contiennent la correction de bug, et donc qui ne sont pas affectées par la vulnérabilité sont les suivantes:

    Stable: 2.19-18+deb8u3
    Sid: 2.21-8

    Vous pouvez utiliser dpkg -l libc-bin pour vérifier quelle version tourne sur votre système. Pensez également à relancer les serveurs/services qui utilisent la libc (donc tous, hein). C'est bien joli d'avoir une version à jour sur le disque, si elle est pas chargée en mémoire et utilisée ça sert à rien. Si possible, rebootez même, vu le tas de trucs qui utilisent la libc, c'est probablement l'option la plus safe.

    Sinon, vous pouvez utiliser lsof | grep 'libc-' pour voir la liste des process qui utilisent l'ancienne libc :

    systemd 1 root DEL REG 8,2 24382311 /lib/x86_64-linux-gnu/libc-2.19.so
    systemd-j 140 root DEL REG 8,2 24379415 /lib/x86_64-linux-gnu/libc-2.19.so
    atd 311 daemon DEL REG 8,2 24379415 /lib/x86_64-linux-gnu/libc-2.19.so
    cron 312 root DEL REG 8,2 24379415 /lib/x86_64-linux-gnu/libc-2.19.so
    ntpd 320 root DEL REG 8,2 24379415 /lib/x86_64-linux-gnu/libc-2.19.so
    [...]
    exim4 26832 Debian-exim DEL REG 8,2 24382311 /lib/x86_64-linux-gnu/libc-2.19.so
    sshd 29321 fabien mem REG 8,2 1738176 24379470 /lib/x86_64-linux-gnu/libc-2.19.so
    bash 29322 fabien mem REG 8,2 1738176 24379470 /lib/x86_64-linux-gnu/libc-2.19.so
    openvpn 29691 nobody mem REG 8,2 1738176 24379470 /lib/x86_64-linux-gnu/libc-2.19.so

    Sur cette machine, on peut voir que sshd, openvpn et bash utilisent la nouvelle version, mais que systemd, exim4, atd ou cron utilisent l'ancienne version (fichier DEL donc supprimmé sur le disque), et donc qu'il faut les relancer.

    Debian testing (Strech) est toujours vulnérable à cette heure.

    • [^] # Re: Debian

      Posté par  (site web personnel) . Évalué à 4.

      C'est également disponible sur Ubuntu depuis hier soir (au moins sur 14.04 LTS).

    • [^] # Re: Debian

      Posté par  . Évalué à 5.

      Ha, systemd utilise encore la libc.

      • [^] # Re: Debian

        Posté par  . Évalué à 10.

        Cher camarade, je vous rappelle que nous ne sommes pas encore Vendredi. Merci de votre compréhension.

        • [^] # Re: Debian

          Posté par  . Évalué à 4.

          Désolé, je suis complétement décalé, j'ai pris mon lundi.

    • [^] # Re: Debian

      Posté par  (site web personnel) . Évalué à 4.

      Merci pour l'astuce du lsof !

      Ce soir à 20h, Strech est lui aussi patché :

      glibc (2.21-8) unstable; urgency=critical
      * Update from upstream stable branch:
      - Fix an integer overflow in hcreate() and hcreate_r() (CVE-2015-8778).
      Closes: #812441.
      * patches/any/local-CVE-2015-7547.diff: new patch to fix glibc getaddrinfo
      stack-based buffer overflow (CVE-2015-7547).

    • [^] # Re: Debian

      Posté par  (Mastodon) . Évalué à 4.

      Voir aussi checkrestart (paquet debian-goodies) et needrestart (backports pour stable), pour savoir quoi redémarrer après une mise à jour.

  • # Test de l'exploitation

    Posté par  (site web personnel, Mastodon) . Évalué à 10.

    Voici ce que donne l'exploitation "officielle" https://github.com/fjserna/CVE-2015-7547 sur une Debian "sid" (alias "unstable").

    On git clone le code et on lance le serveur DNS méchant (il faut être root car il écoute sur le port privilégié 53) :

    % sudo python CVE-2015-7547-poc.py

    On modifie le /etc/resolv.conf pour utiliser ce résolveur DNS ("nameserver 127.0.0.1"). On teste :

    % wget http://rue89.com/
    --2016-02-17 15:59:53-- http://rue89.com/
    Resolving rue89.com (rue89.com)... zsh: segmentation fault wget http://rue89.com/
    Patatras, on a bien la bogue :-( Le serveur affiche :

    [UDP] Total Data len recv 27
    [UDP] Total Data len recv 27
    Connected with 127.0.0.1:60873
    [TCP] Total Data len recv 58
    [TCP] Request1 len recv 27
    [TCP] Request2 len recv 27
    Et, vu avec tcpdump, cela donne (notez la taille de la réponse UDP, 2569 octets…) :

    16:49:27.565275 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 69: 127.0.0.1.40012 > 127.0.0.1.53: 50702+ A? rue89.com. (27)
    16:49:27.565306 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 69: 127.0.0.1.40012 > 127.0.0.1.53: 1856+ AAAA? rue89.com. (27)
    16:49:27.575962 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 2569: 127.0.0.1.53 > 127.0.0.1.40012: 1856| 0/0/0 (2527)
    16:49:27.576263 00:00:00:00:00:00 > 00:00:00:00:00:00, ethertype IPv4 (0x0800), length 74: 127.0.0.1.45586 > 127.0.0.1.53: Flags [S], seq 1826763891, win 43690, options [mss 65495,sackOK,TS val 1657736187 ecr 0,nop,wscale 7], length 0
    Maintenant, on patche (remettre un résolveur qui marche, puis "aptitude update && aptitude dist-upgrade" puis remettre le résolveur méchant dans resolv.conf). Et on réeessaie :

    % wget http://rue89.com/
    --2016-02-17 18:12:27-- http://rue89.com/
    Resolving rue89.com (rue89.com)... failed: Name or service not known.
    wget: unable to resolve host address ‘rue89.com’
    C'est parfait, on n'est plus vulnérable.

  • # Slackware non vulnérable

    Posté par  (site web personnel) . Évalué à 8.

    Curieusement, Slackware ne semble pas être vulnérable au problème, du fait d'un patch spécifique appliqué aux sources de glibc :
    discussion et détails sur le forum LinuxQuestions.

    Explications de Patrick Volkerding, mainteneur de la distribution :

    The proof of concept exploit does not work on any version of Slackware unless that patch (glibc-2.10-dns-no-gethostbyname4.diff.gz) is removed and glibc is recompiled. The patch came from openSUSE long ago, and was also used by Debian at one time, but we seem to be the only ones who still apply it. I've had two requests in email to remove the patch since glibc had supposedly fixed the issue that prompted it, but left it in place anyway. Maybe luck, maybe slack.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.