1 puntos por GN⁺ 12 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Solo con una falla en el protocolo interno de la ruta de git push era posible lograr ejecución remota de código en el backend; GitHub.com ya fue mitigado, pero GHES requiere aplicar el parche
  • La push option, una entrada controlada por el usuario, entraba tal cual en el encabezado X-Stat, lo que permitía inyectar un campo nuevo con un solo punto y coma; además, se abusó del comportamiento de last-write-wins, donde el valor posterior de una misma clave sobrescribe al anterior
  • Al combinar los campos inyectables rails_env, custom_hooks_dir y repo_pre_receive_hooks, era posible eludir el sandbox y ejecutar hooks desde una ruta elegida por el atacante con privilegios del usuario git
  • El mismo mecanismo también permitió inyectar el flag de enterprise mode en GitHub.com, confirmando ejecución de código en un shared storage node, lo que además dejaba accesibles repositorios de otros usuarios y organizaciones en ese nodo
  • Esto muestra cómo, en una arquitectura multiservicio donde distintos servicios confían en un formato compartido, la combinación de falta de sanitización de entrada, rutas de ejecución no productivas y ausencia de validación de rutas puede convertirse en una vulnerabilidad grave

Respuesta inmediata y alcance del impacto

  • En GitHub.com este problema ya fue mitigado y no se requiere ninguna acción adicional
  • GitHub Enterprise Server requiere atención inmediata, y debe actualizarse a GHES 3.19.3 o superior, que incluye la corrección de CVE-2026-3854
  • El rango de versiones vulnerables es GHES 3.19.1 o inferior; las versiones corregidas indicadas son 3.14.24, 3.15.19, 3.16.15, 3.17.12, 3.18.6, 3.19.3
  • Al momento de redactarse, el 88% de las instancias de GHES seguían siendo vulnerables
  • La información técnica adicional y los procedimientos de recuperación de GitHub pueden consultarse en el blog de seguridad de GitHub
  • Los clientes de Wiz pueden identificar instancias vulnerables de GHES con la consulta preconstruida del Wiz Threat Center

Contexto de la investigación y enfoque

  • La infraestructura interna de git de GitHub procesa todas las rutas de git push, y varios servicios internos están escritos en distintos lenguajes de programación
  • En este tipo de estructura multiservicio, las diferencias en cómo cada componente analiza y confía en los datos compartidos pueden derivar en vulnerabilidades
  • Antes, extraer y auditar la gran cantidad de binarios compilados tipo caja negra que conforman este pipeline requería demasiado tiempo y trabajo manual
  • Con herramientas potenciadas por IA y reverse engineering automatizado basado en IDA MCP, fue posible analizar rápidamente los binarios compilados y reconstruir el protocolo interno
  • En ese proceso, se rastrearon de forma sistemática los puntos donde la entrada del usuario afectaba el comportamiento del servidor a lo largo de todo el pipeline, y se descubrió una falla fundamental en el flujo de entrada

Arquitectura interna y límites de confianza

  • Cuando git push entra por SSH, la solicitud fluye por babeld, gitauth, gitrpcd y luego el pre-receive hook
  • babeld es el punto de entrada para todas las operaciones de git y recibe la conexión SSH, mientras que la autenticación se delega a gitauth
  • gitauth verifica las credenciales del usuario y los permisos de push sobre el repositorio, y devuelve políticas de seguridad como límites de tamaño de archivo o reglas para nombres de ramas
  • Con base en esa respuesta, babeld construye el encabezado interno X-Stat con metadatos de seguridad
  • gitrpcd recibe el encabezado X-Stat y configura el entorno de los procesos posteriores, confiando por completo en babeld sin autenticación propia
  • El pre-receive hook verifica límites de tamaño de archivo, reglas de nombres de ramas, integridad de LFS y hooks personalizados definidos por administradores antes de aceptar el push
  • La pieza clave era el encabezado X-Stat, que contenía pares key=value separados por ;
  • Los servicios internos dividían X-Stat por ; y llenaban un mapa; si una misma clave aparecía dos veces, el valor posterior sobrescribía al anterior según la regla de last-write-wins
  • babeld también añadía al X-Stat las push options pasadas con git push -o, en campos como push_option_0, push_option_1 y push_option_count

Causa de la vulnerabilidad: inyección de campos en X-Stat

  • babeld copiaba al encabezado X-Stat valores de push options controlados por el usuario sin sanitizar los puntos y coma
  • Como ; era el separador de campos en X-Stat, un solo punto y coma dentro de una push option permitía salir del campo original y crear un nuevo campo controlado por el atacante
  • Por ejemplo, al inyectar large_blob_rejection_enabled=bool:false dentro de push_option_0, el valor posterior sobrescribía el bool:true establecido previamente
  • Este comportamiento se confirmó tanto mediante análisis de binarios como en capturas de paquetes de instancias reales de GHES
  • Al combinar reverse engineering con análisis a nivel de wire, se mapearon los campos inyectables de X-Stat
  • En particular, se identificaron como sensibles para la seguridad los campos rails_env, custom_hooks_dir, repo_pre_receive_hooks, large_blob_rejection_enabled, reject_sha_like_refs y user_operator_mode
  • Entre ellos, rails_env, custom_hooks_dir y repo_pre_receive_hooks eran las tres piezas clave que llevaban a la ejecución remota de código

Ruta hacia RCE en GHES

  • GHES admite custom pre-receive hooks que se ejecutan antes de aceptar un push
  • El binario de pre-receive tenía dos rutas de ejecución diferenciadas únicamente por el valor rails_env de X-Stat
  • Si el valor era production, ejecutaba los hooks dentro de un sandbox; con cualquier otro valor, los ejecutaba directamente con los privilegios del usuario de servicio git, sin sandbox ni aislamiento
  • Por eso, al inyectar un valor no productivo en rails_env, era posible evadir el sandbox
  • Luego, al inyectar custom_hooks_dir, el atacante podía controlar el directorio base donde se buscaban los scripts de hooks
  • Finalmente, al inyectar en repo_pre_receive_hooks una definición de hook con path traversal, la resolución de rutas del binario combinaba el directorio controlado por el atacante con la carga de traversal y terminaba apuntando a una ruta arbitraria del sistema de archivos
  • La ruta de ejecución no productiva ejecutaba directamente esa ruta resuelta, sin argumentos, sin sandbox y como usuario de servicio git
  • En una validación real, un solo git push devolvió la salida uid=500(git), confirmando RCE con privilegios del usuario git
  • Con esos privilegios era posible obtener control total sobre la instancia de GHES, incluida lectura y escritura del sistema de archivos y visibilidad sobre la configuración de servicios internos

Escalamiento a GitHub.com y exposición entre tenants

  • Al aplicar la misma cadena de explotación a un repositorio de GitHub.com, al principio el push tuvo éxito pero los custom hooks no se ejecutaron
  • Al inyectar user_operator_mode=bool:true y comparar la salida de depuración en ambas plataformas, se vio que en GitHub.com no se alcanzaba la ruta de código de custom hooks
  • Más reverse engineering confirmó la existencia en X-Stat de un flag booleano que controlaba si el servidor operaba en enterprise mode
  • En GHES, este flag era true por defecto, por lo que la ruta de custom hooks siempre estaba activa; en GitHub.com, el valor predeterminado era false, así que en condiciones normales esa ruta no se alcanzaba
  • Como este flag también podía inyectarse con el mismo mecanismo, bastaba con añadir un campo más para que toda la cadena de explotación funcionara también en GitHub.com
  • Después, se recibió desde la infraestructura interna de GitHub.com el resultado de ejecutar hostname, confirmando RCE en GitHub.com
  • GitHub.com es una plataforma multitenant, por lo que los repositorios de múltiples usuarios y organizaciones se almacenan en infraestructura backend compartida
  • La ejecución de código ocurrió en un shared storage node, donde el usuario git tiene amplios permisos de sistema de archivos para procesar todas las operaciones de repositorios de ese nodo
  • Si ese usuario se ve comprometido, también pueden leerse repositorios de otras organizaciones y usuarios presentes en el nodo, sin importar su propietario
  • Al enumerar las entradas del índice de repositorios accesibles desde dos nodos comprometidos, cada uno contenía millones de entradas, incluyendo repositorios de otros usuarios y organizaciones
  • No se accedió al contenido real de repositorios de otros tenants; solo se usaron cuentas de prueba propias para verificar que los permisos de sistema de archivos del usuario git permitían leer todos los repositorios del nodo

Lecciones clave y cronograma de divulgación

  • Con un solo git push, era posible explotar una falla del protocolo interno y obtener ejecución remota de código en la infraestructura backend
  • Cuando varios servicios escritos en distintos lenguajes intercambian datos mediante un protocolo interno compartido, las suposiciones de confianza de cada servicio se convierten en superficie de ataque
  • En esta cadena, un servicio insertaba sin cambios el valor de una push option, otro confiaba en todos los campos de X-Stat, y el pre-receive hook asumía que en producción rails_env siempre sería production
  • Las rutas de código no productivas dentro de binarios de producción, la ausencia de validación contra path traversal en scripts de hooks y la falta de sanitización de entrada en protocolos basados en delimitadores son patrones que pueden aparecer en otros codebases
  • Los equipos que operan arquitecturas multiservicio deben revisar especialmente cómo fluyen las entradas controladas por el usuario a través de protocolos internos, sobre todo cuando configuraciones sensibles de seguridad derivan de formatos de datos compartidos
  • En esta investigación, herramientas de reverse engineering asistido por IA, incluido IDA MCP, permitieron acelerar el análisis de binarios compilados y la reconstrucción de protocolos internos
  • A medida que estas herramientas maduren, probablemente tendrán un papel cada vez más importante para encontrar esta clase de vulnerabilidades que requieren análisis profundos entre componentes
  • Según el cronograma de divulgación, la vulnerabilidad de inyección de push option en X-Stat se descubrió el 2026-03-04; ese mismo día se confirmó el RCE en GHES 3.19.1, se reportó a GitHub y también se desplegó la corrección en GitHub.com
  • El 2026-03-10 se asignaron CVE-2026-3854 y CVSS 8.7, y se publicó el parche para GHES
  • El 2026-04-28 se hizo pública

1 comentarios

 
Comentarios de Hacker News
  • Básicamente hicieron que en los headers de seguridad críticos que configura el servicio interno de autenticación también entrara una cadena arbitraria puesta por el usuario final con git push -o
    es fácil decirlo después, pero aun así esto resulta demasiado absurdo

  • El enfoque de reversing asistido por IA muestra muy bien las fortalezas actuales de los agentes LLM
    como son modelos entrenados intensamente con código, pueden acelerar muchísimo la comprensión de sistemas internos complejos
    la investigación de seguridad normalmente combina 1) entender comportamientos internos complejos y 2) encontrar vulnerabilidades dentro de eso,
    y muchas veces, una vez que se revela el mecanismo interno real, la vulnerabilidad en sí puede volverse sorprendentemente obvia
    CVE-2026-3854 no era un caso inmediatamente obvio incluso conociendo el interior,
    pero si este command injection hubiera estado expuesto en una superficie de ataque más tradicional o más accesible, probablemente lo habrían encontrado muy rápido

    • ya había señales de que la IA tenía fortalezas en ingeniería inversa de C++ o en portar masivamente C++ a C simple
      pero últimamente da la impresión de que esa tendencia se ha desordenado un poco, o incluso de que algunos la obstaculizan a propósito para proteger el lock-in de dev/vendor que nace de la complejidad sintáctica de C++
  • Casi parece que hay gente de Wiz trabajando ahí, porque el resultado se ve bastante bueno
    el producto, pese a un crecimiento extremo y a la inflación de funcionalidades, todavía aguanta bastante bien,
    y el equipo de seguridad encuentra cosas realmente interesantes con frecuencia

    • hay mucha gente salida de Unit 8200
    • hay demasiado ruido, así que nosotros solo usamos un pipeline personalizado con osv-scanner y trivy para ver únicamente lo crítico
    • no trabajo ahí, pero cuando lo probamos en nuestra empresa lanza alertas constantemente por comportamientos completamente inofensivos
      pero al mismo tiempo se queda callado ante tareas bastante sospechosas como consultar el DC por CLI y resetear credenciales, lo cual resulta decepcionante
  • Cuando babeld reenvía la solicitud de push, mete las push options en el header X-Stat de la solicitud interna,
    y ese valor es una cadena arbitraria puesta por el usuario con git push -o
    pero copiaron el valor tal cual sin sanitizar los punto y coma,
    y como ; es el separador de campos en X-Stat, eso permite escapar del campo original y que el atacante cree campos nuevos
    de verdad es el tipo de error más simple posible, tan al alcance que parece fruta tan baja que ya quedó enterrada bajo tierra

    • ah, la mamá de Bobby Tables sí que era muy lista
  • Incluso siendo una vulnerabilidad que encontraron antes de que se explotara,
    no sé si hacía falta meter miedo innecesario con expresiones como BREAKING, unauthorized access y millions of repositories
    https://x.com/wiz_io/status/2049153209982140718

    • eso no significa que esas expresiones sean inexactas
      GitHub tuvo suerte de que quien se topó con esto fuera el fuzzing de Wiz y no un atacante patrocinado por un Estado
  • Que el 88% de las instancias de GHES todavía no haya aplicado un parche crítico de seguridad publicado hace 7 semanas se ve bastante serio
    https://docs.github.com/en/enterprise-server@3.19/admin/release-notes#3.19.3

    • GHES en la práctica ha estado casi abandonado durante años
      aplicar incluso una release de nivel parche requiere horas de downtime,
      y ni siquiera hay una forma de upgrade HA soportada, así que hasta a los clientes responsables les cuesta seguir de inmediato la última versión
      cuando te quejas, todos te dicen que te pases a GitHub Enterprise Cloud,
      pero en tiempos como estos también es dudoso cuánta gente elegiría eso con confianza
      aun así, GHES al menos tiene la ventaja de que no se cae con las interrupciones diarias de github.com
    • muchos clientes on-prem tienen GHES detrás de una VPN,
      y parece que intentan programar el upgrade para una fecha con poco impacto operativo
      aun así, si es una instancia pública, debería actualizarse de inmediato
      solo con la información del artículo y el código fuente público de GitHub Enterprise no parece difícil idear una reproducción
    • en enterprise, si actualizas fuera del calendario regular y todo explota, te puede tocar asumir la responsabilidad,
      o puedes seguir el calendario y esperar que no pase nada; por lo general se elige lo segundo
    • en entornos donde no pueden usar github.com porque se toman la seguridad muy en serio,
      no sería raro que un producto on-prem se actualice una sola vez al año
    • en instalaciones grandes, lo central es cuán frágil es el proceso de upgrade
      en software enterprise con mucho volumen de datos, era común que cualquier detalle menor rompiera la instalación y obligara al equipo operativo a hacer rollback
      los upgrades de SharePoint de antes casi se sentían como tirar los dados
  • Esto también es un gran logro de Wiz,
    y se siente como un punto de inflexión que muestra cuánto empujan las herramientas de IA al RE y al descubrimiento de rutas de compromiso

    • por eso también se agrieta el argumento de que no hay que publicar el código fuente para que la IA lo comprometa menos
      es otro dato más de que la seguridad no debe depender de security through obscurity
  • Todos hablan de reemplazar GitHub, pero entonces queda la pregunta de qué usar
    si incluso un lugar del tamaño de GitHub termina teniendo RCE, no es fácil asegurar que otras alternativas sean mejores

    • también se puede bromear con que Thomas Dohmke lo resolverá todo con un proyecto nuevo, no se preocupen
      https://news.ycombinator.com/item?id=46961345
      https://news.ycombinator.com/item?id=47712656
    • la respuesta más realista parece ser tener Forgejo self-hosted como forge de origen,
      y usar GitHub solo como mirror mientras se aprovecha el CI gratuito
      los secretos se pueden dejar en un proveedor de secret-hosting aparte
    • nosotros nos cambiamos hace 6 meses de GitHub a Forgejo self-hosted y nos ha funcionado de maravilla
      todavía me cuesta creer que Forgejo responda así de rápido y que GitHub se haya vuelto así de lento
    • ahora separamos claramente los proyectos internos de los proyectos públicos
      los internos van en una instancia privada de Forgejo, y los públicos se suben a GitHub pero se espejan en Forgejo
      me sorprendió que Forgejo fuera prácticamente un binario único y tan fácil de configurar,
      y como todos los servicios internos apuntan a Forgejo, habría muy poca fricción si hubiera que dejar GitHub
    • GitLab self-hosted detrás de una VPN también funciona bastante bien
      con la imagen Docker todo-en-uno y unos cuantos GitLab runner alcanza para equipos pequeños o medianos,
      y no hay razón para complicarse hasta la versión en Kubernetes salvo que realmente haga falta
  • Ya era impresionante que la IA encontrara vulnerabilidades en código fuente,
    pero lograrlo incluso en ejecutables binarios de verdad sorprende mucho
    tiene un potencial enorme tanto para bien como para mal
    y una vez más queda la lección de que no hay que tratar los datos como comandos
    toda entrada de usuario debe sanitizarse

    • Transformer originalmente es una arquitectura diseñada para traducción
      así que que sea fuerte en source-to-source o text-to-source ya era algo conocido,
      y que también encaje bien para entender versiones en asm quizá no sea algo totalmente inesperado
      aun así, sigue siendo impresionante
  • Me pregunto si realmente será posible determinar si esto fue explotado

    • por lo que veo, esta vulnerabilidad parece explotable incluso por un usuario anónimo
      con logs del protocolo HTTP/git probablemente se pueda comprobar hasta cierto punto si hubo explotación,
      pero es posible que no haya quedado registro de a qué se accedió realmente ni de quién lo hizo
      si el exploit podía ejecutarse de forma independiente en el servidor git, por definición podría esquivar el logging