Shell shock : un obus dans les dents de bash

Mon dieu, mais c’est horrible !

Il faut avouer que ça ne présage pas d’une franche partie de rigolade.

Tout d’abord, de nombreux programmes interagissent avec le shell. Nous savons que ce n’est généralement pas une bonne idée mais cela nous simplifie parfois grandement la tâche (on dit souvent qu’un bon développeur est un développeur fainéant). La surface d’attaque est donc très étendue.

Par ailleurs, si les systèmes « évidents » seront patchés (un serveur web par exemple), certaines machines plus obscures ne le seront pas : pensez par exemple à des périphériques tels que les caméras connectées (ou plus largement tout ce que vous pouvez trouver sur l’Internet des objets). Rien n’exclut qu’elles exposent des services basés sur des scripts shell et si ce shell est bash, le périphérique devient vulnérable. Comme il y a fort à parier qu’aucune procédure de mise à jour de ces périphériques n’ait été définie, ces périphérques resteront vulnérables ad vitam aeternam.

J’exige des explications

Bash permet d’exporter des variables mais aussi des fonctions à destination d’autres instances de bash. L’export de fonction utilise une variable d’environnement portant le nom de la-dite fonction dont la valeur commence par () { :

foo=() {
    du code
}

À l’import, il se contente aveuglément d’interpréter cela en remplaçant le signe « = » par une espace. C’est ainsi que bash ne se limite pas à interpréter le corps de la fonction mais qu’il poursuit le parsing et exécute les commandes qui suivent la définition de la fonction. Par exemple, définir une variable d’environnement de cette sorte :

FOO=() { ignored; }; /bin/yolo

exécutera /bin/yolo quand l’environnement sera importé par bash.

Ainsi, tout système utilisant bash est vulnérable, mais il est particulièrement vulnérable :

  • s’il expose un service sur le réseau (a fortiori sur Internet) ;
  • que ce service exploite des paramètres passés par le client et qu’il les stocke dans une variable d’environnement ;
  • et que ce service lance bash pour un traitement quelconque.

Pour savoir si votre machine est vulnérable, vous pouvez lancer :

$ env VAR='() { 0; }; echo danger' bash -c "echo bonjour"

Si tout va bien, vous devriez observer ceci :

$ env VAR='() { 0; }; echo danger' bash -c "echo bonjour"
bash: warning: VAR: ignoring function definition attempt
bash: error importing function definition for `VAR'
bonjour

Si tout ne va pas bien, vous observerez :

$ env VAR='() { 0; }; echo danger' bash -c "echo bonjour"
danger
bonjour

À noter que Linux n’est pas le seul système touché. Tous les systèmes Unix (ce qui inclut Mac OS) sont concernés.

M’enfin, qui serait assez bête pour exposer un machin bash sur Internet ?

Moi – et probablement vous aussi – mais je ne pense pas que ce soit de la bêtise.

Pour l’instant, le vecteur de propagation semble être la requête HTTP à destination d’un script CGI. Le serveur web Apache httpd utilise par exemple des scripts (donc potentiellement bash) pour certaines fonctions C, Python ou PHP (si ce dernier est lancé en mode CGI). C’est ainsi que quelques robots parcourent en ce moment même le web en positionnant leur en-tête User-Agent comme suit afin de dresser leur annuaire des machines vulnérables : User-Agent: () { :; } /bin/ping -c x.y.z.q. Si vous souhaitez vérifier vos logs HTTP, vous pouvez lancer egrep '\(\ *\)\ *\{' /var/log/nginx/* par exemple.

Ce n’est donc pas si rare et c’est sans compter les applications largement déployées qui utilisent CGI (cPanel par exemple).

Enfin – et plus localement, certains clients DHCP utilisent également des scripts pour configurer le système. Si le serveur est corrompu (ou mal intentionné), cela permet d’exécuter des commandes – vraisemblablement en root – sur la machine cliente.

Il ne peut plus rien nous arriver d’affreux maintenant

Une fois le patch passé, vous devriez déjà être plus sereins. Néanmoins, comme l’indique RedHat, le patch fourni laisse quelques trous dans la raquette. Il est notamment possible, sous certaines conditions, d’exécuter du code contenu dans des variables d’environnement (CVE-2014-7169). Reste à attendre le patch du patch.

Pour tester votre vulnérabilité à CVE-2014-7169, vous pouvez lancer :

$ env X='() { (a)=>\' sh -c "echo date"; cat echo

Si vous obtenez la date, votre système est vulnérable.

À suivre, donc.

Tweet about this on TwitterShare on FacebookGoogle+Share on LinkedIn
Blabla

3 réflexions au sujet de « Shell shock : un obus dans les dents de bash »

  1. Bonjour Alban,
    Bravo pour la réactivité, sachant que j’ai appris la présence de cette vulnérabilité qu’hier !
    Maintenant, sous OSX, il va falloir attendre le bon vouloir d’Apple…

    1. Sous OSX, j’aurais tendance à ne pas attendre le correctif d’Apple.

      Si tu utilises Homebrew, tu peux te débrouiller par toi-même en installant bash par ce biais (brew update ; brew install bash). Une fois que c’est fait, tu peux éditer /etc/shells en commentant /bin/bash et en ajoutant /usr/local/bin/bash.

      A noter que ça ne te protège pas des scripts qui déclareraient en en-tête #!/bin/bash (au lieu d’un #!/usr/bin/env bash). Mais tu peux toujours créer un lien symbolique pour arranger les choses :

      $ sudo mv /bin/bash /bin/bash.vuln
      $ sudo ln -s /usr/local/bin/bash /bin/bash

      Je n’ai pas de Mac sous la main ici donc je ne te garantis pas que c’est complètement transparent et que ça ne casse rien… Si tu le fais, je veux bien un retour !

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *


*