mercredi 7 septembre 2011

Parler ou pas de Diginotar?

En ce moment, on entend énormément parler de l'EPIC FAIL de Diginotar qui s'est fait pirater. Mais cela vaut il la peine d'en parler? Nous savons que l'architecture SSL d'internet repose sur la confiance que l'on donne à une liste d'autorités installées par défaut dans notre navigateur.
News0ft a écrit un excellent post de blog expliquant pourquoi SSL est cassé. Il faut aujourd'hui compléter son post de blog en ajoutant que l'architecture SSL est encore plus cassée si l'on prend en compte la faible sécurité des infrastructures des entreprises délivrant des certificats.


On refait le match:
A l'origine, nous avons un blogueur iranien qui détecte à l'aide du public key pinning de google chrome que le certificat de gmail n'est pas le bon. Il envoie un message sur twitter, puis le security circus s'emballe et s'enflamme.
Résultat de ce bruissement, pas grand chose. On savait déjà qu'il est possible de faire du MiTM sur SSL tant qu'on a un certificat adéquat, on savait déjà que les CA sont le maillon faible de l'architecture de confiance, et le seul fait finalement intéressant et à discuter concerne l'EPIC FAIL de diginotar.


EPIC FAIL:
La lecture du compte-rendu de l'attaque par l'entreprise Fox-It est édifiante. Dans l'ordre, nous avons:
  • des serveurs webs non patchés (Un message intéressant de F-secure indique que les serveurs webs de diginotar ont été hackés une première fois en mai 2009 (!) Ceci dit, nulle part n'est indiqué comment cette date a été trouvée.)
  • une infrastructure critique sans antivirus, le pirate a pu utiliser des outils comme Cain&Abel.
  • un mot de passe faible
  • un unique domaine windows, ce qui permet avec un seul login/mdp de naviguer sur l'ensemble du réseau
  • un accès direct à l’infrastructure de signature de certificats, alors que la règle veut que ces machines soient déconnectées de tout réseau (et pour y avoir travaillé, je confirme que j'ai vu dans des grandes entreprises la CA sur un portable déconnecté du réseau dans un coffre).
  • Le pirate a pu générer plus de 500 certificats (!!!) et les récupérer. Il devient évident que la CA de diginotar doit être évacuée des magasins de certificats.
La timeline des évènements m'étonne également beaucoup:
  • Le 6 juin 2011 le pirate arrive.
  • Le 17, il a la main sur la DMZ
  • Le 19 juin Diginotar détecte la compromission (et que font ils? Ils prennent le café? Ils font une réunion pour se tenir chaud?)
  • Le 2 juillet le pirate essaye de créer des certificats. Le 10 juillet, il y arrive, le premier est celui de *.google.com
  • Le 20 juillet, le dernier certificat est créé. 
  • Le 27 juillet, une requête OCSP pour *.google.com arrive chez diginotar. 
  • A partir du 4 août, un énorme afflux de requêtes OCSP proviennent de l'iran.
  • Le 27 août un message est posté sur un forum google (27 selon le rapport, 28 selon le message du forum?)
  • Le 29 Août le faux certificat de google est révoqué. 
  • Le 1er septembre OCSP fonctionne sur un mécanisme de whitelist, je suppose que c'est face à l'étendue de la débâcle découverte par Fox-it.
Et le pirate:
Le pirate semble être le même que Comodohacker. Son message sur pastebin semble véridique, et le rapport note quelques similitudes entre les deux attaques. Un seul point diffère entre l'analyse de Fox-it et les dires du pirate: il affirme s'être connecté sur un réseau déconnecté d'internet pour faire signer ses certificats, Foxit indique que l'architecture signant les requêtes était joignable depuis un réseau d'administration.
Il a posté deux nouveaux messages confirmant son attaque. [tiens, je vais supprimer Globalsign de mon magasin de certificats juste au cas où :-) ]
Update: Cela se confirme, Globalsign a décidé de ne plus signer de certificats le temps de vérifier ses infrastructures.
Update: le pirate continue d'émettre sur pastebin ses messages. Rien de neuf si ce n'est qu'il indique être très fort et qu'il faut le prendre très au sérieux.


Sooooo, what's the point?
Eh bien on apprend qu'un pirate peut attaquer avec succès des sociétés délivrant des certificats, et que de ce fait les communications SSL peuvent être écoutées. Comme je disais en introduction, rien de bien neuf, cela vaut il la peine d'en parler? Sur internet, "trust, but verify" est de mise. Je rappelle les extensions firefox données sur le blog de News0ft: perspectives et certificate patrol.
Update: On lit encore sur internet des déclarations outrées sur le fait que le pirate ait pu avoir l'accès à la clé privée de la CA de diginotar. Je ne pense pas qu'il y ait eu accès, s'il avait cette clé, il n'aurait jamais fait signer par diginotar ses +500 certificats. Je pense à la lecture du compte-rendu de FoxIt et du message de ComodoHacker que le pirate n'a eu accès qu'au workflow de signature de certificats, a pu ajouter les siens puis récupérer les certificats signés à la sortie. En ce sens, il y a du FAIL chez diginotar qui aurait du détecter que le nombre de certificats variait, de plus des alertes devraient être levées dès que des wildcards ou des certificats au nom de "google" ou autre nom sensible sont demandés.

Par contre, puisqu'on apprend actuellement toutes les semaines que des grandes infras sont piratées, je jetterai bien une idée en l'air. Et si on imaginait que nos infras étaient piratées? Là, maintenant. Qu'on lance le même genre d'investigations poussées suite à un incident avéré. Qui serait capable de lancer un audit complet? Que trouverions nous dans nos infras?

jeudi 1 septembre 2011

kernel.org est compromis.

Le site kernel.org est le site officiel du développement du noyau linux. Il s'agit d'un site massivement mirroré au travers du monde. Un des serveurs, hera.kernel.org (indisponible à cette heure) a été compromis. Le message du site central est éloquent: "Security Breach".  Le message qui suit est une traduction commentée du message initial diffusé sur kernel.org.

La compromission fût détectée fortuitement le 28 Août par un administrateur qui a lu des messages d'erreurs étranges dans le /dev/mem lié à Xnest alors qu'Xnest n'était pas installé... Ceci me fait penser à la vidéo de Nicolas Ruff sur les APT que j'ai visionnée sur le blog de Cédric Blancher. Une des diapositives de sa présentation indique: "Les compromissions sont souvent découvertes par hasard"...

Une seconde analyse attentive du serveur par les administrateurs à montré qu'un troyen était lancé automatiquement au reboot de la machine, signe évident de compromission. De plus les fichiers liés à ssh (openssh, openssh-server et openssh-clients) ont été modifiés et étaient en cours d'utilisation. Apparement le programme malveillant loggait les actions des utilisateurs du système. Une analyse élargie a montré que plusieurs autres serveurs présentaient des erreurs curieuses une fois de plus liées à Xnest, sans qu'il ne soit possible à l'heure actuelle de faire le lien formel entre compromission et messages d'erreurs Xnest. Quoi qu'il en soit, il est conseillé à tous les développeurs noyaux impliqués de vérifier la présence de ce genre de messages sans qu'il ne soit plus donné de précisions (Que faut il chercher? un crash? oops? autre type d'erreur?).

La compromission initiale s'est faite en deux temps selon les administrateurs. L'attaquant aurait utilisé un login/mot de passe (soit faible, soit obtenu par un moyen tiers ce n'est pas précisé) pour obtenir un shell local puis aurait utilisé une faille inconnue pour devenir root. Des recherches sont en cours, une note indique que le noyau 3.1rc2 pourrait bloquer cette attaque sans plus de certitudes.

Une grosse opération de nettoyage est en cours puisque les machines ont toutes été mises off-line pour analyse. Les autorités (haha) américaines et européennes ont été prévenues. Toutes les machines de kernel.org vont être réinstallées. Les 448 utilisateurs de ces machines vont devoir changer de mots de passes et/où de clé SSH.  Et enfin tous les fichiers composant le noyau linux sont analysés, ainsi que les tarballs pour s'assurer qu'aucune modification n'y a été effectuée.

Le message d'alerte termine sur une note positive en indiquant que l'attaque est inutile car le mode de développement de liux est basé sur git. Git calcule un hash SHA-1 de chacun des fichiers composant l'arbre des sources. Il n'est donc pas possible de modifier un de ces fichiers, et donc l'attaquant n'a pas de possibilités de "trojaniser" un noyau linux qui sera diffusé par la suite. Un deuxième avantage lié au mode de développement décentralisé de linux fait qu'il existe une quantité innombrable de duplicata de ces sources, permettant ainsi de détecter le changement entre deux versions. Le message termine par ces mots "(we) are confident that our systems, specifically git, have excellent desgin to prevent real damage from these types of attacks".

Dans un sens, oui, ils ont raison, mais je ne suis pas rassuré pour autant. Je ne suis pas développeur, je n'utilise donc pas git, je ne peux donc pas compter sur son mécanisme de checksums élaboré. Je télécharge mes noyaux en tar.bz2 sur un des mirroirs cités plus haut en vérifiant sa signature. Et la vérification de signature, http://www.kernel.org/signature.html, le dit bien: "This signature does not guarantee that the Linux Kernel Archives master site itself has not been compromised.". Donc à l'heure actuelle, je ne vais sûrement pas télécharger de noyaux :-) Le second point qui m'inquiète toujours un peu dans ce genre de compromissions c'est le flou artistique (apache, redhat) qui entoure la compromission. La communication est toute à leur honneur et est je pense essentielle. Néanmoins, j'aimerai également (vœu pieux) un gros travail de communication rétroactif une fois la crise passé pour pouvoir prendre le temps d'analyser cette compromission à froid.

EDIT: les serveurs ne sont toujours pas remontés. Linux Torvalds a choisi de migrer l'arbre des sources sur github.

jeudi 25 août 2011

Apache range header et CVE-2011-3192

Apache est vulnérable à une attaque par déni de service. L'origine de ce CVE débute le 20 Août sur la mailing liste full disclosure par un message de Kingcope. Il propose en effet un petit outil en perl killapache.pl réalisant un denial of service sur les serveurs web apache, toutes versions confondues. Je propose une analyse rapide de celui-ci en deux points: tout d'abord une explication de cette attaque, ensuite les moyens d'en réduire l'impact.

1/ L'attaque
Une lecture rapide du code perl montre qu'il utilise le header HTTP Range. Une explication claire de ce header HTTP est disponible ici. Pour résumer, un serveur HTTP peut ne renvoyer que quelques parties d'un fichier sur demande d'un client à l'aide de l'entête "Range".
Cet outil d'attaque, killapache.pl, envoie une première requête afin de s'assurer que le serveur distant accepte d'envoyer des morceaux de fichiers (des "Range") et si oui l'attaque est lancée [Attention, cette vérification n'est pas fiable, c'est à dire qu'un serveur marqué non vulnérable peut l'être..]. L'outil analyse le code retour de la première requête en cherchant le mot "Partial".

J'ai utilisé socat afin de voir l'attaque fonctionner 'in vivo'. Depuis un xterm je lance donc:
kevin@slackware:~$ socat - TCP-LISTEN:8080,reuseaddr,fork


D'un autre xterm je lance l'attaque (après avoir modifié le script pour qu'il tape le port 8080, constante PeerPort):
kevin@slackware:~$ perl kill_apache.pl 127.0.0.1 

Il suffit d'observer l'attaque après avoir renvoyé "Partial" (une réponse non RFC mais suffisante pour que l'attaque soit lancée):
[je coupe un peu, c'est long.  snip--- snip--- snip--- vous comprenez l'idée de cette ligne d'en-tête. ]
Et les requêtes s'enchaînent.

L'attaque devient évidente. En réponse à ces requêtes, le serveur va donc prendre la page d'accueil du site web attaqué, la zipper 1300 fois puis découper ces 1300 fichiers zippés afin de renvoyer les bonnes parties de celui-ci au client.
Finesse supplémentaire de l'attaque, ce n'est pas un GET, mais un HEAD qui est demandé. Donc le serveur va calculer une très grosse quantité de données et n'en renvoyer que le début ! Nous sommes donc en présence d'un DoS de belle facture où le client avec quelques requêtes va provoquer énormément de travail sur un serveur sans être lui-même impacté.

2/ Mitigations
Un ensemble de bons conseils ont été donnés sur la mailing list apache. Il n'existe pas de solution unique, je décris les idées émises.

Nous avons vu que l'en-tête Range est utile pour n'envoyer qu'une partie des fichiers. Cet en-tête est donc particulièrement employé pour des sites pourvoyeurs de gros pdfs (genre e-readers) ou de videos. En dehors de ces cas ou autre emploi similaire (Webdav?), la désactivation de cet en-tête est la solution la plus simple à mettre en oeuvre:
  RequestHeader unset Range

Une deuxième solution propose de limiter la longueur des en-têtes. Les images ci-dessus montrent que l'en-tête Range: ne fait qu'une seule ligne. La directive de configuration:

        LimitRequestFieldSize 200
permet de bloquer effectivement cette attaque. Deux points sont à considérer. Tout d'abord certains autres en-têtes peuvent légitimement avoir besoin d'une taille supérieure ce qui provoquera un blocage du service se servant de cette en-tête. C'est donc à adapter au cas par cas. Ensuite, cette attaque est appelée à évoluer et il apparaît comme crédible qu'elle fonctionnera avec un en-tête plus petit.

Une troisième solution préconise de limiter le nombre de champ Range dans la même requête au nombre de 5 (limite arbitraire, à adapter, des cas légitimes d'usages existent). Ceci se fait via un module apache développé pour l'occasion, ou des directives de configuration (expliquées dans le mail apache).

Enfin, la dernière solution consiste à attendre :-) Les développeurs apache ont promis une solution dans les 48 heures.

Pour l'historique, L'en tête Range: a déjà souffert d'une faille légèrement similaire en requêtant plusieurs fois le même morceau de fichier: CVE-2007-0086. Mon conseil serait donc de désactiver cet en-tête à moins que le site web en fasse un usage vital. Deux CVE sur un même en-tête HTTP risquent de donner des idées à des attaquants qui chercheront à affiner/modifier cette attaque pour qu'elle soit la plus efficace possible en étant moins bruyante.

3/conclusion
C'est effectivement un attaque fructueuse, certains messages sur des mailings listes indiquent que la machine s'est mise à swapper de manière démesurée jusqu'à provoquer un blocage complet. Les méthodes de mitigation sont très effectives et clairement exposées dans le mail apache. Une proposition d'évolution de la norme HTTP RFC 2616 est faite suite à discussion sur une ML apache.
Ceci dit, je suis surpris qu'on ne parle pas de IIS ou nginx, alors que ceux-ci savent utiliser Range et la compression. Peut-être un autre CVE, je n'ai pas de IIS ou nginx pour tester. Quelqu'un? :-)

EDIT: Le correctif apache, http://www.apache.org/dist/httpd/Announcement2.2.html Edit (bis): il ne s'agit pas du correctif attendu, merci à "Anonyme" de l'avoir signalé. Edit (ter): le lien est correct, la mise à jour est annoncée, c'est bien le 2.2.20 qui corrige ce CVE.
EDIT secondaire: testé rapidement sur un lighttpd et un nginx, conf par défaut après un apt-get debian. Les deux semblent non vulnérables, j'ai plus de CPU consommé par le script killapache.pl que par le webserver :-)