Sécurité renforcée : correction d’une vulnérabilité ImageMagick
Le jeudi 20 juin 2019, notre capitaine du support a déclenché l’alerte rouge : une vulnérabilité venait d’être signalée, permettant d’obtenir un accès root sur un serveur Transloadit. Il s’agit du niveau de privilège le plus élevé possible sur une machine et du pire cauchemar de tout ingénieur en sécurité ou fondateur de startup technologique.

Dans cet article, nous expliquons comment le piratage s’est produit, quelles en ont été les conséquences, ce que nous avons fait et ce que nous prévoyons encore de faire pour éviter que cela ne se reproduise.
Contexte
Transloadit utilise de nombreux outils d’encodage pour manipuler et convertir des médias. Pour les images, nous utilisons ImageMagick, un projet que nous sponsorisons depuis de nombreuses années. Aujourd’hui encore, nous devons beaucoup à ImageMagick.
Les clients de Transloadit bâtissent leur activité sur la nôtre et attendent de ces fondations qu’elles soient solides. Il nous est donc difficile de modifier ou de mettre à jour nos logiciels, car cela change les comportements de manière plus ou moins subtile. C’est pourquoi, jusqu’à présent, nous avons lancé de nouvelles versions de stack (English) tout en rendant leur utilisation facultative. Les clients peuvent tester les nouvelles stacks quand cela leur convient, pendant que les anciennes versions continuent de fournir le service qu’ils attendent et sur lequel ils comptent.
La version la plus ancienne, connue en interne sous le nom imagemagick_stack v1.0.0, est prise en charge par nos soins depuis dix ans. Nous avions l’intention de la déprécier, mais cela doit se faire en douceur. Si nous retirons une brique essentielle des fondations de nos clients, leur activité pourrait s’effondrer. Comme dans tout logiciel, on y découvre des bugs et des vulnérabilités qu’il faut corriger. ImageMagick ne fait pas exception. Au fil des ans, quelques vulnérabilités graves ont été découvertes dans imagemagick_stack v1.0.0. L’une d’elles permettait d’exécuter des commandes système dissimulées dans des images SVG spécialement conçues.
Cela place Transloadit entre le marteau et l’enclume. D’un côté, nous devons fournir ces fondations robustes qui ne changent jamais ; de l’autre, nous devons mettre à jour les logiciels vulnérables pour ne pas exposer nos clients à des risques. Nous avons résolu ce dilemme en choisissant une troisième voie : déprécier les logiciels vulnérables en douceur. Nous aidons nos clients à abandonner progressivement l’ancien, tout en gagnant le temps nécessaire grâce au confinement du logiciel défaillant.
Notre confinement consiste à :
- Limiter ce à quoi nos machines d’encodage ont accès. En l’occurrence, uniquement à des fichiers temporaires hachés, à S3 et à la récupération de Jobs dans une file d’attente.
- Analyser les images SVG (et similaires) à la recherche de commandes système et rejeter celles qui en contiennent avant qu’ImageMagick ne les traite.
- Exécuter nos processus sous un utilisateur non privilégié qui n’a accès à aucun secret, hormis ce que l’utilisateur root a injecté dans la mémoire de son processus.
Ce qui s’est passé
Le 20 juin, Jeremy Matos, ingénieur sécurité senior chez GitLab, a signalé qu’un hacker avait obtenu un accès root à l’un de nos serveurs. GitLab menait une campagne HackerOne dans laquelle l’entreprise invite des hackers à révéler des vulnérabilités et offre des récompenses pour toute tentative de piratage réussie qui lui est divulguée de manière responsable. GitLab a racheté Gitter.im en 2017, et Gitter (imaginez Slack, mais pour les projets open source) utilisait nos services depuis 2014. Lorsque vous envoyiez une image avec vos messages de chat dans Gitter, le processus de téléversement et de redimensionnement pouvait être pris en charge par la plateforme de Transloadit.
Le chercheur en sécurité Sergey Kashatov a participé à ce programme et a tenté de compromettre Gitter.im, propriété de GitLab, en téléversant une image contenant une charge malveillante. Il pensait avoir trouvé une vulnérabilité chez GitLab, mais il ignorait alors que l’image était en fait traitée sur nos serveurs, et que c’est donc Transloadit qu’il avait compromis. Jeremy s’en est rapidement rendu compte et a relayé la conversation avec Sergey jusqu’à ce que nous puissions contacter Sergey directement et comprendre comment il avait obtenu l’accès root.
Comment c’est arrivé : l’analyse de la « cause racine »
Dans How Complex Systems Fail, Richard I. Cook explique que
« L’attribution a posteriori [de l’]accident à une “cause racine” est fondamentalement erronée. Parce qu’une défaillance manifeste nécessite de multiples fautes, il n’existe pas de “cause” isolée d’un accident. Les accidents ont de multiples contributeurs. »
S’il existe sans doute des nuances et qu’il suffit parfois de désigner l’anomalie principale ayant contribué à l’incident, nous estimons utile, dans ce cas précis, d’en présenter plusieurs.
Comme indiqué plus haut, nous connaissions les vulnérabilités de la stack ImageMagick v1.0.0 et limitions les dommages potentiels par les mesures suivantes :
Exécution de nos processus sous un utilisateur non privilégié
Cette sécurité a cédé lorsque nous avons introduit un nouveau lanceur de processus plus tôt cette année. Pour tenter d’atténuer la lenteur de la lecture des métadonnées, nous voulions mieux exploiter les capacités multicœurs de nos machines d’encodage et paralléliser ce travail en lançant plusieurs instances du même processus. Pour ce faire, nous avons mis en place un orchestrateur existant, déjà largement utilisé en production.
Cependant, lors de la migration vers ce nouveau superviseur, nous avons omis de vérifier qu’il
lançait toujours ses processus sous l’utilisateur dépourvu de privilèges. Il lançait au contraire
les processus d’analyse des métadonnées sous l’utilisateur ubuntu, qui a
le privilège d’accéder à davantage de fichiers et même de devenir root.
Cela est passé inaperçu pour deux raisons : A) nous n’avions pas de surveillance en production
pour vérifier que nos processus tournaient toujours sous l’utilisateur limité, et B) en
développement et en test, nous exécutons tout sous le même utilisateur par commodité, si bien que
cette situation paraissait parfaitement normale à la plupart des développeurs.
Analyse de sécurité des images SVG (et similaires)
Notre filtrage, censé rejeter les charges malveillantes, recherche tous les vecteurs d’attaque possibles, mais ne le faisait pas de manière récursive pour les inclusions. Les fichiers SVG peuvent faire référence à d’autres fichiers afin de les intégrer. En ce sens, ils ressemblent beaucoup aux fichiers HTML : un fourre-tout de balises XML décrivant la manière dont les éléments doivent être rendus, pouvant même inclure d’autres images. Alors que d’autres hackers avaient choisi de livrer directement des charges malveillantes, Sergey a décidé de téléverser un SVG valide faisant référence à un autre fichier contenant les commandes système malveillantes. Il a masqué cette inclusion et lui a donné une extension .jpeg, trompant encore davantage notre système, qui a cru pouvoir la transmettre sans danger à ImageMagick.
Conséquences
Sergey a divulgué ce problème de manière responsable et n’a ni volé ni supprimé de données. Il est bien sûr possible qu’un autre hacker ait exploité cette vulnérabilité avant que Sergey ne la découvre, et qu’il ait volé ou supprimé des données. Notre enquête n’a révélé aucune preuve en ce sens, mais cette hypothèse ne peut être totalement exclue.
Si un hacker malveillant avait utilisé cette faille et obtenu un accès root à une machine d’encodage, il aurait pu :
- Inspecter les fichiers temporaires. Ces fichiers correspondent à l’entrée ou à la sortie d’un Robot et n’existent que brièvement sur la machine d’encodage. Les fichiers temporaires sont toutefois nommés par un UUIDv4 sans tirets et ne peuvent pas être rattachés à l’utilisateur ou au client d’origine.
- Accéder aux buckets S3 de Transloadit
Petit point positif dans cette découverte alarmante : quelques années plus tôt, nous avions déjà limité ce à quoi nos machines d’encodage ont accès. Ainsi, même avec un accès root, les machines ne pouvaient accéder ni aux ressources AWS (hormis S3), ni à notre base de données, ni aux secrets de nos clients.
Mesures correctives
Naturellement, nous avons immédiatement :
- Amélioré notre filtrage pour prendre en compte les charges malveillantes référencées en externe ;
nous n’autorisons plus ce type d’image rare sur une stack vulnérable. L’Assembly
se termine désormais par une erreur et affiche un avertissement vous invitant à passer à la stack
v2.0.3. - Supprimé le nouveau processus superviseur et rétabli l’exécution de notre processus sous un utilisateur non privilégié, en ajoutant une surveillance en production afin d’être alertés si cela venait à changer de nouveau.
- Créé une bibliothèque C qui empêche ImageMagick d’effectuer la moindre requête réseau de son propre chef.
- Effectué la rotation de toutes nos clés (par exemple pour nos propres buckets S3) et restreint encore davantage l’accès IAM des machines d’encodage, qui n’ont désormais qu’un accès en écriture aux quelques buckets dont elles ont besoin (par exemple tmp.transloadit.com). Nous avons aussi grandement simplifié la rotation des clés, afin de pouvoir la faire en un clin d’œil par mesure de précaution générale.
- Rémunéré Sergey pour son travail, puisque GitLab a manifestement pour politique de ne pas pouvoir accorder de récompenses pour des vulnérabilités découvertes sur des systèmes qu’elle ne gère pas elle-même.
- Mis à jour toutes nos machines vers la dernière LTS d’Ubuntu : bionic, qui garantit quatre années supplémentaires de correctifs et offre des outils supplémentaires pour isoler davantage nos processus d’encodage.
Cela devrait résoudre les problèmes immédiats. Nous avons demandé à Sergey de confirmer que Transloadit n’est plus vulnérable, ce qu’il a reconnu. Cela ne veut pas dire pour autant que nous en avons terminé. Il nous reste encore à :
- Utiliser l’utilisateur non privilégié en développement et en test également. Cela pourrait ralentir un peu le développement, mais c’est cet écart entre production et développement qui a permis à cette vulnérabilité de passer inaperçue.
- Exploiter nos nouveaux outils du système d’exploitation pour isoler davantage nos processus d’encodage et ne leur donner accès qu’au fichier temporaire sur lequel ils travaillent.
- Lancer la procédure de dépréciation pour supprimer imagemagick_stack v1.0.0. Nous allons
identifier qui l’utilise encore et afficher des avertissements leur rappelant de tester une stack
plus récente. Nous enverrons également un e-mail aux clients et leur proposerons toute l’aide
nécessaire pour adopter en douceur des stacks plus modernes. Lorsque le dernier client aura cessé
de l’utiliser, nous supprimerons complètement
v1.0.0. - Mettre en place une liste d’autorisation des variables d’environnement pour nos outils d’encodage. Même si nos machines d’encodage n’ont qu’un accès en écriture à nos buckets S3, ImageMagick n’a vraiment aucune raison d’en avoir connaissance.
Recommandations
Nous ne pensons pas qu’une rotation des mots de passe soit nécessaire de votre côté, puisqu’il n’y a eu aucun accès à des mots de passe ou à des données similaires. Rien n’indique que cette attaque ait été menée avec succès avant Sergey. Si nous considérons un accès non autorisé aux fichiers d’encodage temporaires comme le pire scénario possible, la situation n’est heureusement pas si sombre. Ces fichiers temporaires sont anonymisés, souvent incomplets (car en cours de téléchargement) et supprimés dès que l’encodage a eu lieu et que le téléversement est terminé.
Nous ne pouvons toutefois pas exclure qu’un hacker ait obtenu des fichiers temporaires et, bien sûr, le média lui-même pourrait contenir des informations permettant une identification (par exemple, une photo montrant le badge nominatif d’une personne, ou encore un panneau de rue qui révèle où elle se trouve ; et si ces photos étaient transmises à Google ou Facebook, ces entreprises pourraient identifier la personne représentée). C’est pourquoi nous vous recommandons d’en informer vos clients, comme nous vous en informons.
Heureusement, aucune information d’accès n’a fuité à la suite de cette vulnérabilité, mais ce n’est pas une raison pour baisser la garde. Même si nous travaillons chaque jour pour atteindre les plus hauts niveaux de sécurité, une sécurité à 100 % restera toujours un mythe. Il vaut donc mieux ne nous donner qu’un accès en écriture à un seul bucket, voire à un seul dossier, plutôt que de nous donner un accès root à tout, simplement pour que nous puissions écrire dans ce bucket ou ce dossier.
Et si ce n’est pas déjà fait, il est également judicieux de mettre à jour votre
Robot /image/resize vers
"imagemagick_stack": "v2.0.3".
Conclusion
Cette situation nous a profondément inquiétés. Protéger nos clients à tout prix est vital pour la pérennité de Transloadit, et notre entreprise est tout pour nous. Ces dernières semaines, nous avons travaillé jour et nuit pour déployer des mises à jour afin que ce genre d’incident ne puisse plus jamais se produire. Nous travaillons également avec Sergey et d’autres chercheurs en vulnérabilités comme lui pour y parvenir. D’autres mises à jour sont encore à venir, mais nous avons déjà ressenti le besoin de divulguer ce problème de sécurité. Nous espérons que cela vous laissera, en tant que client, suffisamment de temps pour y faire face de la manière la plus adaptée à votre activité.
Je regrette profondément les erreurs commises de notre côté qui ont conduit à la présence de cette vulnérabilité en production. Si vous avez des questions ou des inquiétudes après cette lecture, n’hésitez pas à me contacter. Je me ferai bien sûr un plaisir de vous apporter toutes les précisions nécessaires.
