Hosts con instancias de GitLab potencialmente vulnerables.
Introducción
GitLab es un sistema de repositorio de código abierto para el desarrollo de software, utilizado principalmente por grandes organizaciones para gestionar DevOps y otros proyectos de software relacionados. La oferta principal de GitLab está gestionada y alojada por la propia empresa GitLab; también ofrecen una versión autoalojada de su producto tanto para comunidades como para empresas con distintos niveles de soporte.
El 7 de mayo de 2021, un investigador llamado "vakzz" (William Bowling) informó de un desagradable fallo que afectaba al software empresarial y comunitario GitLab a través del programa de recompensas por fallos HackerOne. Los ingenieros de GitLab solucionaron rápidamente el problema, y la vulnerabilidad pareció pasar desapercibida durante unos meses. Eso fue hasta que un usuario en Twitter informó de que una botnet de miles de instancias de GitLab comprometidas inició una campaña DDoS masiva, generando más de un terabit de datos por segundo(eso son 75.000 ZD/m (Discos Zip por minuto)).
![](https://lh6.googleusercontent.com/bVG1OtZn7_xiLj1PtHEs-GuXaAyKqTo-iwITprJrzuJ1sEtmR9cxS0yGGktwNprGK3tihUks_9nWvfNQ2JGh_4-6S4BpanCPccThWFFV07f5VZTmQtnMoY711kljxILhaJFpaVp_)
¿Cuál es el problema?
Según el informe original, las imágenes subidas al servidor de GitLab pasan por una herramienta Perl llamada ExifTool para eliminar los metadatos inútiles. Por desgracia, ExifTool también es compatible con el formato de archivo DjVu, que procesará las S-Expressions definidas por el usuario, un lenguaje de evaluación similar a LISP que se encuentra en secciones específicas del archivo DjVu. Un bug relacionado, CVE-2021-22204, fue anunciado en Abril de 2021, donde el mismo investigador mostró que ExifTool DjVu no saneaba adecuadamente las entradas antes de llamar a la función Perl eval(), permitiendo la ejecución arbitraria de código Perl controlada por el usuario (Ejecución Remota de Código). William Bowling escribió un excelente resumen en su blog con más detalles sobre la investigación que condujo a estos hallazgos.
En el momento de escribir estas líneas, Censys encontró 20.524 hosts con acceso a Internet que ejecutaban 20.565 servicios identificados como una versión vulnerable del software de servidor GitLab. La mayoría de los hosts ejecutaban la versión 11.11, con más de 1.400 casos, seguidos de cerca por las versiones 13.1 y 12.1, con unos 1.300 hosts.
Aunque el servidor de GitLab no disponía de ninguna función que nos permitiera determinar la versión específica del software en ejecución, ideamos un método eficaz de identificación y huella digital utilizando artefactos (literales) del proceso de compilación de GitLab.
GitLab iniciará automáticamente un conjunto de tareas que compilan y prueban el software de GitLab cada vez que se etiqueta una confirmación de código. Una parte de este proceso de compilación es un trabajo llamado "compile-production-assets
" que se encuentra en el directorio ".gitlab/ci/frontend.gitlab-ci.yml
"cuyo objetivo es agregar y compilar los activos públicos del producto (imágenes y archivos CSS) en una carpeta de salida. Dado que estos archivos son accesibles al público sin autenticación y se hace referencia a ellos en un índice expuesto del sitio web de GitLab (por lo tanto, se pueden buscar en Censys), eran candidatos perfectos para un poco de huella digital ad hoc.
Muchos de estos nombres de archivo generados apenas cambian (como el logotipo), pero otros sí. Por ejemplo, "public/assets/application.css" parecía tener un nombre de archivo generado diferente para cada versión menor. Además, los nombres de estos archivos incluirán una cadena codificada ASCII-HEX de 64 bytes añadida al nombre de archivo original, lo que nos permite asignar estos nombres de archivo a la tarea de compilación y a la versión de software que los generó. Nuestro objetivo era descargar todas las compilaciones etiquetadas (con una versión vulnerable) del software GitLab, anotar el nombre del archivo generado con el prefijo "public/assets/application-" y la extensión "css", y asociar ese nombre de archivo con la etiqueta de la compilación. No es perfecto, pero sirve.
Después de descargar todas las imágenes vulnerables de docker.io (las 247 principales, secundarias y candidatas a versión), ejecutamos un pequeño script de shell que generó una tabla de nombres de etiqueta con nombres de archivo únicos que dio como resultado 44 hashes de nombre de archivo únicos:
#!/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
Después de un poco de poda manual de datos, comenzamos la búsqueda generando una sentencia SQL BigQuery para encontrar todos los servicios GitLab en ejecución junto con el nombre de archivo específico que estábamos buscando. Los resultados se almacenaron en una tabla temporal de la base de datos para su posterior análisis. (Una función a la que tienen acceso los clientes empresariales de Censys ):
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;
El siguiente paso fue tomar los datos generados por la consulta anterior y asignar los nombres de archivo encontrados a su respectiva versión, tal y como se ve en las imágenes docker, lo que dio como resultado lo siguiente:
Archivo |
Versión mapeada |
Recuento de anfitriones |
/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 |
También podemos construir una consulta de búsqueda algo verbosa en Censys utilizando los hashes anteriores para ver mejor los hosts que coinciden con estas condiciones buscando tanto el nombre de archivo gitlab_logo como la lista de archivos que coinciden.
![](https://lh5.googleusercontent.com/DLR68txN6PBh1zM1jW_S5xwpSHOp1xya5XFDvCihMO1UZL5XluZ-uFZmALdUFrCD95cpdOEwV6bMe2-h5j65MZRYlWWd0UuM-N0RzkKWbh6N41YfSQTUlpquYFP6U__wiGCHlXg7)
Aunque el uso de estos hosts explotados para DDoS es terrible en sí mismo, también se ha hablado de otros ataques de explotación masiva en los que se encontraron usuarios administradores aleatorios. Por ejemplo, un atacante podría introducir puertas traseras y funcionalidades vulnerables en el código fuente de los proyectos alojados en estos servicios. Si esto ocurriera, incluso el código escrito de forma más segura podría convertirse en una pesadilla administrativa.
El ataque en sí es sencillo, y existen exploits fácilmente disponibles que hacen de este un problema grave que debe ser tratado de inmediato. Esperamos que los datos presentados en este post ayuden a los ingenieros y administradores a identificar y parchear las instancias vulnerables de GitLab.
¿Qué hago al respecto?
Referencias