Reports
CRÍTICA[RCE]#1154542

Cómo un fichero de imagen trucado lograba ejecución remota en GitLab (ExifTool)

GitLab pasaba las imágenes subidas por ExifTool para limpiar metadatos; renombrando un fichero DjVu como .jpg se colaba código Perl que el servidor ejecutaba. Es la CVE-2021-22205.

Resumen
Resumen en castellano de un reporte público, no una traducción literal. El código y los comandos se mantienen como en el original.

Resumen

Este es de esos fallos que dan un poco de vértigo por lo pequeño que es el gesto que lo dispara: subir una imagen. En GitLab, cuando subías un fichero con extensión jpg, jpeg o tiff, el componente Workhorse lo pasaba por ExifTool para quitarle los metadatos que no estuvieran en la lista blanca. Una medida de higiene de lo más razonable… salvo por un detalle.

ExifTool no se fía de la extensión: mira el contenido del fichero para decidir qué es. Así que renombrando el fichero se podía obligar a que entrara en juego cualquiera de sus analizadores, no solo el de JPEG o TIFF. ¿El problema? Uno de esos formatos soportados es DjVu, y al procesar su anotación ExifTool pasaba los tokens por un eval de Perl para "convertir secuencias de escape de C". Ahí estaba la puerta.

Pasos de reproducción

La validación intentaba asegurarse de que todo estuviera bien escapado, pero se le escapaba (nunca mejor dicho) un caso: una barra invertida seguida de un salto de línea. Con eso se podían cerrar las comillas e inyectar Perl que se ejecutaba tal cual:

(metadata
	(Copyright "\
" . qx{echo vakzz >/tmp/vakzz} . \
" b ") )

Con esa anotación dentro de un fichero DjVu, el resto es casi decepcionantemente sencillo:

  1. Renombrar ese fichero DjVu como echo_vakzz.jpg.
  2. Crear un snippet nuevo y, en la descripción, pulsar "Attach a file".
  3. Subir el fichero.
  4. Comprobar que en el servidor ha aparecido /tmp/vakzz: el comando se ejecutó.

Cambiando ese echo por una reverse shell, subir el fichero a https://gitlab.com/-/snippets/new devolvía directamente una shell en producción, con el usuario git:

id
uid=500(git) gid=500(git) groups=500(git)
hostname -a
web-09-sv-gprd

Impacto

Aquí no hay que adornar mucho: es ejecución remota de código sin autenticación previa real, porque adjuntar un fichero es algo que puede hacer casi cualquiera. Se convirtió en la CVE-2021-22205 y, por desgracia, en una de las más explotadas en masa contra instancias de GitLab sin actualizar. Un servidor de código fuente comprometido a este nivel es, básicamente, las llaves de todo lo que hay dentro.

Remediación

GitLab dejó de invocar a ExifTool de esa manera sobre ficheros no confiables y actualizó la dependencia. Pero la lección de fondo va más allá del parche concreto: nunca dejes que un analizador decida por su cuenta el tipo de un fichero que viene del usuario y lo procese con toda su potencia. Si algo tiene que "convertir" o "normalizar" datos ajenos, que lo haga aislado y con el mínimo de funcionalidad posible; ese eval escondido dentro de una librería de metadatos es justo lo que nadie audita hasta que es tarde.