Volver al Blog

El fallo de Gitea «requiere permiso de escritura». El formulario de registro te lo da

Armario de red mural con la puerta abierta en el cuarto trastero de una oficina, con cajas de cartón, una fregona y estanterías

Hay dos textos oficiales sobre el mismo agujero de Gitea. Uno dice que el atacante necesita permiso de escritura en un repositorio. El otro, en la misma página, dice que no necesita ningún privilegio. Parece una errata y no lo es: es la descripción exacta de cómo viene configurado el producto cuando lo instalas.

Hablamos del CVE-2026-60004, corregido el 27 de julio en Gitea 1.27.1 y explotado desde hace unos días. Afecta a todo lo que haya entre la versión 1.17 y la 1.27.0, las dos incluidas. La misma publicación cerraba un segundo agujero igual de serio, el CVE-2026-59774, una lectura arbitraria de ficheros que ni siquiera pedía estar autenticado. El primero lo reportó Shai Rod, que firma NightRang3r; el segundo lo encontraron por separado xbow-security y el propio NightRang3r.

Dos frases que parecen incompatibles

La entrada del catálogo de CISA dice, en nuestra traducción, que el fallo «permite a un atacante con permiso de escritura en el repositorio enviar un parche malicioso al endpoint diffpatch para plantar un hook de Git ejecutable y ejecutar órdenes de shell como la cuenta de servicio de Gitea». Léelo deprisa en una reunión de lunes y lo que se queda flotando es «con permiso de escritura». Suena a que hay que ser alguien.

El vector que publica el aviso de los mantenedores es CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, con nota 9,8. Esa PR:N se lee «privilegios requeridos: ninguno». Y el mismo aviso explica por qué, con una frase que no hemos visto citada en ninguna de las coberturas que leímos ayer: «con el registro abierto activado, el ataque lo puede llevar a cabo un visitante sin autenticar tras registrarse una cuenta normal y crear un repositorio» (la traducción es nuestra).

¿Y viene activado el registro abierto? La documentación de configuración de Gitea responde sin ambigüedad. En la sección [service], DISABLE_REGISTRATION vale false, REGISTER_EMAIL_CONFIRM vale false y REQUIRE_SIGNIN_VIEW vale false. Cualquiera que llegue a la URL puede darse de alta sin confirmar el correo, crearse un repositorio y tener permiso de escritura sobre él. El requisito de la ficha se cumple rellenando un formulario. (El alta por OpenID va atada al mismo interruptor: su valor por defecto es el contrario de DISABLE_REGISTRATION, así que se cierra sola cuando cierras el registro, salvo que alguien la haya forzado a mano.)

La pregunta útil cuando lees «requiere autenticación»

En las reuniones de priorización, «requiere autenticación» y «requiere permisos» funcionan como calmantes: bajan el fallo un peldaño en la lista y la reunión avanza. Lo que hay que preguntar es quién puede cruzar ese umbral y en cuánto tiempo. En un servicio interno donde las cuentas las crea una persona a mano, el umbral da margen de verdad. En un servicio con registro abierto publicado en internet, es un trámite de diez segundos. La misma frase de la ficha describe dos riesgos que no se parecen en nada.

Y no es un hallazgo nuestro de hoy: es la tercera vez este verano que acabamos en el mismo sitio. Lo escribimos en agosto a cuenta de un PNG de WordPress que por dentro era PostScript —en un gestor de contenidos, «requiere autenticación» no quiere decir «requiere ser tú», quiere decir «requiere una de las cuentas que se regalan»— y otra vez con el CVE de cPanel donde el riesgo lo ponía el vecino, cuando un 5,6 sin cuenta resultó más urgente que un 8,8 con ella. Tres veces en tres meses ya no es una anécdota: es que la cola de parcheo se ordena por «cuánto daño hace» cuando debería ordenarse también por «cuánto cuesta llegar».

CISA publica junto al CVE su valoración SSVC, que es más útil que la nota numérica y casi nadie mira: explotación activa, automatizable , impacto técnico total. Ese «automatizable: sí» es el que manda. Significa que el descubrimiento, la creación de la cuenta y la ejecución se pueden encadenar en un script que barre internet, y que no hace falta que nadie tenga interés particular en tu empresa para que te toque.

De un parche a un hook

El aviso de los mantenedores detalla el mecanismo con una honestidad poco habitual, y conviene leerlo porque aquí no interviene ninguna función escondida. El endpoint diffpatch aplica el parche que le mandas dentro de un clon bare temporal compartido. Si mandas dos veces el mismo parche se produce una colisión de tipo add/add, y el mecanismo de fusión a tres vías de Git termina escribiendo en disco rutas que estaban en el índice, a pesar de la bandera --cached. En un clon bare, la raíz del repositorio es $GIT_DIR: un fichero ejecutable llamado hooks/post-index-change deja de ser un fichero y pasa a ser un hook vivo, que se ejecuta con la cuenta de servicio la próxima vez que Git escribe el índice.

El propio aviso enumera tres condiciones para que el disparo funcione: Git 2.32 o posterior, la ruta diffpatch habilitada y un sistema de ficheros temporal que sea escribible y ejecutable. Y el arreglo consistió en dejar de usar un clon bare para esta operación. Llámalo bug o llámalo supuesto de diseño que envejeció mal: lo interesante para el resto de nosotros es que ninguna de las piezas era exótica. Los hooks de Git son ejecución de código por diseño, y llevan siéndolo veinte años. Lo que falló fue que el atacante pudiera escribir dentro de $GIT_DIR.

El otro agujero de la misma actualización

Toda la atención se la ha llevado ahora el CVE-2026-60004, y eso deja en la sombra al otro que cerró la misma versión. El CVE-2026-59774 puntúa también 9,8, afecta de la 1.22.1 a la 1.27.0 y es una lectura arbitraria de ficheros a través de la directiva #+INCLUDE de Org-mode, el formato de notas que Gitea sabe renderizar. Bastan un repositorio público y un fichero con el marcado adecuado para leer cualquier cosa que pueda leer la cuenta de servicio. Empezando por app.ini, donde viven el INTERNAL_TOKEN, los secretos de OAuth y de JWT y las credenciales de la base de datos.

Merece la pena señalarlo porque es un patrón que se repite en las publicaciones de seguridad: se cita el CVE más llamativo, se aplica el parche pensando en ese, y el resto de la lista se lee por encima. La versión corregida es la misma para los dos, así que aquí no cambia nada práctico. Cambia la conversación con quien decide: no estás pidiendo una ventana de mantenimiento por un fallo, la estás pidiendo por dos, y uno de ellos no necesita que el atacante tenga absolutamente nada.

Once segundos, según quien lo sufrió

Hay un solo caso público, y conviene decir de dónde sale: lo publicó un desarrollador que firma como Andrey en Habr, la plataforma técnica rusa, y lo recogieron después Help Net Security y The Hacker News. Es un relato del propio afectado, sin verificación de terceros, y aun así es lo más concreto que hay. La secuencia, automatizada de principio a fin: se registró una cuenta, se creó un repositorio, se disparó el exploit, se ejecutó código dentro del contenedor de Gitea como el usuario git, se escribió la prueba del acceso en una rama del propio repositorio, se descargó un cargador genérico y se soltó una carga que parece un minero de criptomonedas. Ese matiz es del propio afectado, que dice no haber podido confirmar ni la familia del minero, ni la cartera, ni el pool. La parte activa duró unos once segundos.

Lo que destapó el asunto llegó por correo: el proveedor de alojamiento avisando de que el servidor virtual llevaba mucho rato por encima del 70 % de CPU, de que eso incumplía las condiciones del servicio y de que le estaban limitando los recursos. Ya habíamos visto ese patrón —el primer aviso entrando por el canal de facturación o el de soporte comercial y no por el de seguridad— cuando escribimos sobre los agentes RMM de proveedores de IT. La consecuencia práctica: si once segundos de ejecución y un consumo de CPU sostenido no disparan nada tuyo, tu umbral de detección está por encima del ruido más escandaloso que puede hacer un intruso.

Qué quedó al alcance de esa cuenta de servicio

El aviso es explícito: la configuración de la aplicación y sus secretos, las credenciales y el contenido de la base de datos, las credenciales de OAuth y de las integraciones, y los repositorios montados. Prácticamente todo lo que un servidor de código necesita para hacer su trabajo, que es exactamente el problema. Un servidor de código no es una herramienta del equipo de desarrollo al nivel del tablero de tareas: es infraestructura de producción, porque es el origen de lo que se despliega y el guardián de las llaves con las que se despliega. Vimos el mismo patrón en el panel de datos que también era el llavero y en las llaves de producción que guarda tu CI/CD. Y por si alguien se consuela pensando que el código lo tiene clonado todo el equipo: clonar no es tener copia de lo que ese servidor guarda.

En el caso de Habr hubo suerte, y la suerte tenía nombre técnico. El contenedor no era privilegiado, así que la carga no sobrevivió a los reinicios; el afectado no encontró rastros de persistencia por cron, por systemd ni por claves SSH nuevas. Su limpieza fue subir a 1.27.2, cerrar el registro, quitar los métodos de alta que sobraban, rotar todos los secretos y tokens, restringir la red de Docker y cortar la salida a internet del contenedor. Ninguna de esas decisiones de contención se tomó durante el incidente: la del contenedor sin privilegios se tomó el día que se montó el servicio, cuando lo cómodo habría sido lo contrario. Es el eje con el que trabajamos: el fallo es inevitable, la avería es una decisión de diseño.

Con un límite que conviene no saltarse, porque es donde el contenedor no ayudó: la contención limitó la persistencia, no la confidencialidad. Todo lo que había dentro se pudo leer durante los segundos que el atacante estuvo ahí. Por eso rotar los secretos es el único punto de la lista de limpieza que no admite hacerse la semana que viene.

Veinte minutos, y hoy

CISA añadió el CVE a su catálogo de vulnerabilidades explotadas el 25 de agosto y dio a las agencias federales estadounidenses hasta el 28. A ti no te obliga nadie, pero esa fecha es la mejor referencia pública que hay sobre a qué velocidad se considera que toca moverse. Si tienes Gitea, esto se hace hoy:

  1. La versión. Todo lo que haya entre 1.17 y 1.27.0 está afectado. La corregida es la 1.27.1; el afectado del caso se fue directamente a la 1.27.2. Desde fuera, la versión suele salir en el pie de la página de login.
  2. El registro. Comprueba DISABLE_REGISTRATION, REGISTER_EMAIL_CONFIRM y REQUIRE_SIGNIN_VIEW. Si nadie los tocó al instalar, están en los valores abiertos.
  3. La exposición y las altas recientes. ¿Contesta desde internet? Shadowserver contaba cerca de 5.000 instancias de Gitea alcanzables públicamente. Y la lista de cuentas creadas desde finales de julio te dirá más que cualquier escáner.
  4. Bajo qué corre. Usuario, privilegios del contenedor, qué volúmenes tiene montados y hacia dónde puede salir. Eso no cambia si te entran: cambia lo que se llevan y cuánto tiempo se quedan.
  5. Rotar. Si la versión era vulnerable y el servicio estaba expuesto, actualizar no expulsa a nadie que ya se llevara un token. Tokens de despliegue, credenciales de base de datos, secretos de OAuth, claves de webhook.
  6. Los rastros. La cadena documentada deja huellas concretas y baratas de buscar: cuentas dadas de alta que nadie reconoce, repositorios recién creados por esas cuentas, ramas nuevas dentro de ellos y llamadas repetidas al endpoint diffpatch en el log de acceso. Con el mismo parche aplicado, esas cuatro comprobaciones son la diferencia entre «hemos parcheado» y «sabemos que no entró nadie».
  7. El responsable. Anota en el inventario quién responde de ese servicio y en qué ventana se actualiza. Si la respuesta honesta es «nadie», ese es el hallazgo del día y el CVE es el detalle.

Cuándo tu caso es distinto

Si tu Gitea solo escucha en la red interna, con las altas cerradas y las cuentas creadas a mano, el registro abierto deja de ser la puerta y la urgencia baja bastante. No desaparece: cualquiera con cuenta y un repositorio propio sigue pudiendo ejecutar código en ese servidor, y en esa lista entra quien se fue de la empresa la semana pasada. Pero es la diferencia entre parchear esta mañana y parchear en la próxima ventana. Decirlo importa, porque el consejo de «parchea todo ya» es el que hace que nadie parchee nada.

Y si no usas Gitea, la lectura que se lleva uno no es sobre Gitea. Cambia el nombre por el del gestor de tareas autoalojado, el panel de métricas, el servidor de documentación o la herramienta de traspaso de ficheros que alguien levantó un martes de hace cinco años porque hacía falta para una semana. La pregunta no es qué versión tienes. Es cuántos de esos servicios están expuestos, quién figura como responsable de cada uno y qué CVE de este verano tienen abierto porque su ficha decía «requiere autenticación».

¿Quién responde de tus servicios expuestos?

Inventariar lo que tienes publicado, ponerle responsable y ventana de actualización, y decidir qué síntoma despierta a una persona es parte de cómo diseñamos y operamos infraestructura y cloud, y de nuestro trabajo de ciberseguridad gestionada. Si prefieres empezar por la lista corta de lo que hay que parchear esta semana, también nos vale.

Hablar con everyWAN

Nota de fuentes

Aviso de seguridad de Gitea GHSA-rcr6-4jqh-j84m: mecanismo, versiones afectadas, las tres condiciones del disparo, el impacto y la puntuación 9,8 con el vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H (la puntuación es del CNA; NVD todavía figura como «Undergoing Analysis»). Nota de publicación de Gitea 1.27.1, del 27 de julio de 2026, para las fechas y los créditos de los dos CVE. Catálogo de vulnerabilidades explotadas conocidas de CISA: entrada CVE-2026-60004 añadida el 25 de agosto de 2026, fecha límite del 28, y valoración SSVC (explotación activa, automatizable sí, impacto técnico total). Documentación oficial de configuración de Gitea para los valores por defecto de registro y OpenID. Relato del incidente y la cifra de los once segundos: publicación del propio afectado en Habr, recogida por Help Net Security el 26 de agosto de 2026 y por The Hacker News, de donde salen el aviso del proveedor por el 70 % de CPU y el matiz de que la carga «parece» un minero sin confirmar. Recuento de instancias expuestas atribuido a Shadowserver vía BleepingComputer. Las traducciones al castellano de las citas son nuestras. Los datos son de esas fuentes; las opiniones sobre priorización, inventario y detección son nuestras.

Ciberseguridad DevOps Vulnerabilidades Infraestructura
Compartir

Suscríbete a nuestra newsletter

Para recibir historias del mundo IT, novedades de everyWAN y ofertas exclusivas para suscriptores, date de alta a nuestra lista de correo

everyWAN
everyWAN