Skip to content
Nouveau livre électronique : Obtenez dès aujourd'hui votre exemplaire du manuel "Unleash the Power of Censys Search Handbook" (Libérez la puissance de la recherche sur ) ! | Télécharger maintenant
Blogs

CVE-2021-22205 : C'était un coup de GitLab

Hôtes disposant d'instances GitLab potentiellement vulnérables.

Introduction

GitLab est un système de dépôt de code open-source pour le développement de logiciels, principalement utilisé par les grandes organisations pour gérer DevOps et d'autres projets logiciels connexes. L'offre principale de GitLab est gérée et hébergée par la société GitLab elle-même ; elle propose également une version auto-hébergée de son produit pour les communautés et les entreprises, avec différents niveaux de support.

Le 7 mai 2021, un chercheur nommé "vakzz" (William Bowling) a signalé un méchant bogue qui ciblait le logiciel d'entreprise et de communauté GitLab via le programme de primes aux bogues de HackerOne. Les ingénieurs de GitLab ont rapidement corrigé le problème, et la vulnérabilité a semblé passer inaperçue pendant quelques mois. Jusqu'à ce qu'un utilisateur de Twitter signale qu'un botnet composé de milliers d'instances GitLab compromises a lancé une campagne DDoS massive, générant plus d'un térabit de données par seconde(soit 75 000 ZD/m (Zip Disks par minute)).

Quel est le problème ?

Selon le rapport original, les images téléchargées sur le serveur GitLab passent par un outil Perl appelé ExifTool pour supprimer les métadonnées inutiles. Malheureusement, ExifTool prend également en charge le format de fichier DjVu, qui traitera les S-Expressions définies par l'utilisateur, un langage d'évaluation de type LISP trouvé dans des sections spécifiques du fichier DjVu. Un bogue connexe, CVE-2021-22204, a été annoncé en avril 2021, dans lequel le même chercheur a montré que l'ExifTool DjVu ne nettoyait pas correctement les entrées avant d'appeler la fonction Perl eval(), ce qui permettait l'exécution de code Perl arbitraire contrôlé par l'utilisateur (exécution de code à distance). William Bowling a écrit un excellent résumé sur son blog avec plus de détails sur la recherche qui a conduit à ces résultats.

À l'heure où nous écrivons ces lignes, Censys a trouvé 20 524 hôtes orientés vers l'internet et exécutant 20 565 services identifiés comme étant une version vulnérable du logiciel serveur GitLab. La plupart des hôtes utilisent la version 11.11, avec plus de 1 400 occurrences, suivie de près par les versions 13.1 et 12.1, avec environ 1 300 hôtes.

Bien que le serveur GitLab ne dispose d'aucune fonction nous permettant de déterminer la version spécifique du logiciel en cours d'exécution, nous avons mis au point une méthode efficace d'identification et d'empreinte digitale à l'aide d'artefacts (littéraux) du pipeline de construction de GitLab.

GitLab lance automatiquement un ensemble de tâches qui compilent et testent le logiciel GitLab chaque fois qu'un commit de code est marqué. Une partie de ce processus de construction est un travail appelé "compile-production-assets"trouvé dans le répertoire ".gitlab/ci/frontend.gitlab-ci.yml"dont l'objectif est d'agréger et de compiler les ressources publiques du produit (images et fichiers CSS) dans un dossier de sortie. Ces fichiers étant accessibles au public sans authentification et référencés dans l'index d'un site web GitLab (donc consultables à l'adresse Censys), ils constituaient des candidats parfaits pour un relevé d'empreintes ad hoc.

Beaucoup de ces noms de fichiers générés ne changent pratiquement jamais (comme le logo), mais certains le font. Par exemple, "public/assets/application.css" semble avoir un nom de fichier généré différent pour chaque version mineure. En outre, les noms de ces fichiers comprennent une chaîne de 64 octets codée en ASCII-HEX ajoutée au nom de fichier original, ce qui nous permet d'associer ces noms de fichiers à la tâche de construction et à la version du logiciel qui les a générés. Notre objectif était donc de télécharger chaque version étiquetée (avec une version vulnérable) du logiciel GitLab, puis de noter le nom du fichier généré avec le préfixe "public/assets/application-" et l'extension "css", et d'associer ce nom de fichier à l'étiquette de la version. Ce n'est pas parfait, mais cela fera l'affaire.

Après avoir téléchargé toutes les images vulnérables de docker.io (les 247 images majeures, mineures et release candidates), nous avons exécuté un petit script shell qui a généré une table de noms de tags pour les noms de fichiers uniques, ce qui a donné 44 hachages de noms de fichiers uniques :

#!/usr/bin/env bash
 
assetdir="/opt/gitlab/embedded/service/gitlab-rails/public/assets"
tags=$(cat ./vulnerable_tags.txt)
 
for tag in $tags; do
    filename=$(docker run --rm -it --entrypoint "" gitlab/gitlab-ce:$tag ls $assetdir|egrep '^application-.*\.css' | grep -v \.gz)
    echo $tag,$filename
done

Après un élagage manuel des données, nous avons commencé la recherche en générant une instruction SQL BigQuery pour trouver tous les services GitLab en cours d'exécution ainsi que le nom de fichier spécifique que nous recherchions. Les résultats ont été stockés dans une table de base de données temporaire en vue d'une analyse ultérieure. (Une fonctionnalité à laquelle les entreprises clientes de Censys ont accès) :

WITH
  results AS (
  SELECT
    DISTINCT host_identifier.ipv4 AS host,
    autonomous_system.asn AS asn,
    autonomous_system.name AS asn_name,
    location.country_code AS cc,
    location.coordinates.latitude AS lat,
    location.coordinates.longitude AS long,
    REGEXP_EXTRACT(SAFE_CONVERT_BYTES_TO_STRING(svc.http.response.body),
        ".*(/assets/application-[a-f0-9]{64}.css).*") AS version,
  FROM
    `censys-io.universal_internet_dataset.universal_internet_dataset`
  JOIN
    UNNEST(services) svc
  JOIN
    UNNEST(svc.http.response.html_tags) x
  WHERE
    DATE(snapshot_date) = "2021-11-03"
    AND SAFE_CONVERT_BYTES_TO_STRING(svc.http.response.body)LIKE '%/assets/application-%.css%'
    AND SAFE_CONVERT_BYTES_TO_STRING(x) LIKE '%/assets/gitlab_logo-%'
  ORDER BY
    version DESC )
SELECT
  *
FROM
  results;

L'étape suivante a consisté à prendre les données générées par la requête ci-dessus et à mettre en correspondance les noms de fichiers trouvés avec leur version respective telle qu'elle apparaît dans les images docker, ce qui a donné le résultat suivant :

Nom de fichier Version mappée Nombre d'hôtes
/assets/application-5440e2dd89d3c803295cc924699c93eb762e75d42178eb3fe8b42a5093075c71.css 11.11 1448
/assets/application-02aa9533ec4957bb01d206d6eaa51d762c7b7396362f0f7a3b5fb4dd6088745b.css 13.10 1416
/assets/application-450cbe5102fb0f634c533051d2631578c8a6bae2c4ef1c2e50d4bfd090ce3b54.css 12.10 1322
/assets/application-45b2cf643afd34888294a073bf55717ea00860d6a1dca3d301ded1d0040cac44.css 12.9 1277
/assets/application-d161b6e25db66456f8e0603de5132d1ff90f9388d0a0305d2d073a67fd229ddb.css 13.9 1157
/assets/application-52560ba2603619d2ff1447002a60dcb62c7c957451fb820f1894e1ce7c23821c.css 13.8 1000
/assets/application-051048a171ccf14f73419f46d3bd8204aa3ed585a72924faea0192f53d42cfce.css 13.6 985
/assets/application-a0c92bafde7d93e87af3bc2797125cba613018240a9f5305ff949be8a1b16528.css 13.7 833
/assets/application-c8d8d30d89b00098edab024579a3f3c0df2613a29ebcd57cdb9a9062675558e4.css 13.0 736
/assets/application-4abc4e078df94075056919bd59aed6e7a0f95067039a8339b8f614924d8cb160.css 13.1 700
/assets/application-def1880ada798c68ee010ba2193f53a2c65a8981871a634ae7e18ccdcd503fa3.css 12.3 699
/assets/application-969119f639d0837f445a10ced20d3a82d2ea69d682a4e74f39a48a4e7b443d5e.css 13.4 639
/assets/application-455d114267e5992b858fb725de1c1ddb83862890fe54436ffea5ff2d2f72edc8.css 13.3 605
/assets/application-3407a4fd892e9d5024f3096605eb1e25cad75a8bf847d26740a1e6a77e45b087.css 12.4 594
/assets/application-aeddf31361633b3d1196c6483f25c484855e0f243e7f7e62686a4de9e10ec03b.css 12.6 567
/assets/application-bec9544b57b8b2b515e855779735ad31c3eacf65d615b4bfbd574549735111e7.css 12.7 557
/assets/application-a9308f85e95b00007892d451fd9f6beabcd8792b4c5f8cd7524ba7e941d479c9.css 13.2 549
/assets/application-77566acc818458515231d0a82c131a42890d771ea998b9f578dc38e0eb7e517f.css 12.0 509
/assets/application-3cbf1ae156fa85f16d4ca01321e0965db8cfb9239404aaf52c3cebfc5b4493fb.css 11.9 458
/assets/application-bf1ba5d5d3395adc5bad6f17cc3cb21b3fb29d3e3471a5b260e0bc5ec7a57bc4.css 13.5.0-ce.0 436
/assets/application-d56f0577fbbbd6f159e9be00b274270cb25b60a7809871a6a572783b533f5a3c.css 12.2 409
/assets/application-38981e26a24308976f3a29d6e5e2beef57c7acda3ad0d5e7f6f149d58fd09d3d.css 11.10.5-ce.0 406
/assets/application-4a081f9e3a60a0e580cad484d66fbf5a1505ad313280e96728729069f87f856e.css 12.8.0-ce.0 371
/assets/application-dc6b3e9c0fad345e7c45a569f4c34c3e94730c33743ae8ca055aa6669ad6ac56.css 12.8 367
/assets/application-d812b9bf6957fafe35951054b9efc5be6b10c204c127aa5a048506218c34e40f.css 12.5 359
/assets/application-78812856e55613c6803ecb31cc1864b7555bf7f0126d1dfa6f37376d37d3aeab.css 12.1 325
/assets/application-93ebf32a4bd988b808c2329308847edd77e752b38becc995970079a6d586c39b.css 11.10 300
/assets/application-73a21594461cbc9a2fb00fc6f94aec1a33ccf435a7d008d764ddd0482e08fc8d.css 12.5.0-ce.0 255
/assets/application-340c31a75c5150c5e501ec143849adbed26fed0da5a5ee8c60fb928009ea3b86.css 12.1.0-ce.0 250
/assets/application-be9a23d3021354ec649bc823b23eab01ed235a4eb730fd2f4f7cdb2a6dee453a.css 13.5 233
/assets/application-34031b465d912c7d03e815c7cfaff77a3fa7a9c84671bb663026d36b1acd3f86.css 11.11.0-rc4 224
/assets/application-67ac5da9c95d82e894c9efe975335f9e8bdae64967f33652cd9a97b5449216d2.css 11.1 171
/assets/application-7f1c7b2bfaa6152740d453804e7aa380077636cad101005ed85e70990ec20ec5.css 13.3.8-ce.0 130
/assets/application-f154ef27cf0f1383ba4ca59531058312b44c84d40938bc8758827023db472812.css 13.2.0-ce.0 61
/assets/application-f9ab217549b223c55fa310f2007a8f5685f9596c579f5c5526e7dcb204ba0e11.css 13.4.0-ce.0 60
/assets/application-ec9dfedd7bd44754668b208858a31b83489d5474f7606294f6cc0128bb218c6d.css 13.1.0-ce.0 60
/assets/application-292ca64c0c109481b0855aea6b883a588bd293c6807e9493fc3af5a16f37f369.css 11.9.0 46
/assets/application-39fdbd63424a09b5b065a6cc60c9267d3f49950bf1f1a7fd276fe1ece4a35c09.css 12.7.0-ce.0 43
/assets/application-9c095c833db4364caae1659f4e4dcb78da3b5ec5e9a507154832126b0fe0f08e.css 11.11.0-rc1.ce.0 6
/assets/application-79837fd1939f90d58cc5a842a81120e8cecbc03484362e88081ebf3b7e3830e9.css 13.7.0-rc3.ce.0 1
/assets/application-2eaf7e76aa55726cc0419f604e58ee73c5578c02c9e21fdbe7ae887925ea92ae.css 11.10.0-rc7.ce.0 1

Nous pouvons également construire une requête de recherche Censys quelque peu verbeuse en utilisant les hachages ci-dessus pour mieux visualiser les hôtes correspondant à ces conditions en recherchant à la fois le nom de fichier gitlab_logo et la liste des fichiers qui correspondent.

Si l'utilisation de ces hôtes exploités pour des attaques DDoS est déjà terrible, des discussions ont également eu lieu sur d'autres attaques d'exploitation de masse où des utilisateurs administrateurs aléatoires ont été trouvés. Par exemple, un attaquant pourrait introduire des portes dérobées et des fonctionnalités vulnérables dans le code source des projets hébergés par ces services. Si cela devait se produire, même le code le plus sûr pourrait devenir un cauchemar administratif.

L'attaque elle-même est simple, et il existe des exploits facilement disponibles, ce qui en fait un problème grave qui doit être traité immédiatement. Nous espérons que les données présentées dans cet article aideront les ingénieurs et les administrateurs à identifier et à corriger les instances GitLab vulnérables.

Que dois-je faire ?

Références

 

A propos de l'auteur

Mark Ellzey
Chercheur principal en sécurité Tous les postes de Mark Ellzey
Mark Ellzey est chercheur principal en sécurité à l'adresse Censys. Avant d'occuper son poste actuel, Mark a travaillé pendant plus de 22 ans en tant qu'ingénieur en sécurité des réseaux et développeur de logiciels pour plusieurs fournisseurs de services Internet et institutions financières.
Solutions de gestion de la surface d'attaque
En savoir plus