Fusión Maliciosa: Código Oculto en Commits de Fusión de Git
Se descubrió código malicioso y ofuscado en el archivo vite.config.js de un proyecto. No se introdujo en una solicitud de extracción (PR), sino directamente en un commit de fusión durante la resolución de conflictos. La vista de PR de GitHub solo muestra la diferencia desde la rama de características, ignorando los cambios realizados en el commit de fusión en sí. El análisis con git log reveló un commit de fusión con commits padres idénticos pero contenido de archivo alterado.
Los hashes MD5 de los commits padres coincidieron:
- Padre 1:
aa82acb0c335430d8300b6cb306dc824(limpio) - Padre 2:
aa82acb0c335430d8300b6cb306dc824(limpio) - Fusión:
2a54754defae4d13aab39f256738dbbf(modificado)
En una fusión de tres vías, Git debería producir un resultado sin cambios cuando los archivos padres son idénticos. Cualquier diferencia indica edición manual durante el proceso de fusión.
Mecanismo de Inyección y Ofuscación
La carga maliciosa se inyectó en dos archivos de diferentes módulos. El colaborador añadió la carga al hacer clic en el botón de fusión en la PR. El código se ejecutó durante npm run dev y npm run build durante 3,5 meses.
Las técnicas de ofuscación incluyeron:
- Reconstruir cadenas como
require,module,constructormezclándolas con una semilla numérica. - Usar
Functionen lugar deevalpara eludir el análisis estático. - Un decodificador personalizado que utiliza una tabla de sustitución de caracteres.
La carga no contenía URLs ni direcciones IP. En su lugar:
- Consultaba la última transacción de una billetera TRON.
- Extraía un hash de transacción BSC.
- Realizaba una llamada JSON-RPC
eth_getTransactionByHasha un nodo BSC. - Decodificaba el código mediante XOR desde el campo
inputde la transacción.
Se usó Aptos como alternativa si TRON no estaba disponible. La ejecución utilizó child_process.spawn con detached: true y stdio: 'ignore', y un temporizador de 30 segundos para contrarrestar la detección en modo vigilancia.
Razones por las que Pasó Desapercibido
- GitHub no muestra diferencias para commits de fusión en PRs.
git logno revela cambios; se necesitagit diff <parent1>..<merge>.- El código se desplazó más allá de la columna 200 usando espacios en blanco.
- Las herramientas SAST fallaron por falta de firmas: sin
eval, URLs o base64.
Esta técnica se conoce como fusión maliciosa — una fusión que introduce cambios no presentes en ninguno de los padres (gitglossary(7)). Fue descrita por un mantenedor de Git en 2013, pero existen pocas herramientas de detección.
Detector de Fusiones Maliciosas: Escáner Automatizado
Un detector escrito en Go compara el resultado esperado de la fusión de tres vías (a través de un ancestro común) con el commit de fusión real. Las discrepancias señalan ediciones manuales.
Uso:
evilmerge scan /ruta/al/repositorio
Opciones:
--format=sarifpara GitHub Code Scanning.- Niveles de severidad: resoluciones manuales de conflictos vs. ediciones sin conflictos.
Integraciones:
- Acción de GitHub:
```yaml
- uses: fimskiy/Evil-merge-detector@v1
with:
fail-on: warning
```
- Aplicación de GitHub: verificaciones de PR y escaneos retrospectivos del historial.
- Plantillas para GitLab, Bitbucket y configuraciones autohospedadas (ganchos pre-receive).
Mitigaciones y Vulnerabilidades del Flujo de Trabajo
Ataques mediante acceso de colaborador: commits legítimos seguidos de inyección durante una fusión. La PR en sí permanece limpia.
Recomendaciones:
- Usar un historial lineal (squash/rebase).
- Implementar ganchos pre-receive en el servidor.
- En GitHub: habilitar "Descartar revisiones obsoletas" para requerir nueva revisión si la rama de PR cambia.
GitHub confirmó que este es un diseño intencional, con posibles restricciones futuras. Las medidas actuales se centran en la prevención, no en la detección.
Conclusiones Clave
- Fusión maliciosa es el término oficial para ediciones manuales en commits de fusión.
- La carga utiliza blockchain (TRON/BSC/Aptos) para comando y control sin URLs/IPs.
- El detector basado en Go escanea el historial y se integra en CI/CD.
- 3,5 meses de actividad no detectada en un proyecto con CI y revisión de código.
- GitHub no tiene planes inmediatos de cambiar el flujo de trabajo de fusión.
— Editorial Team
Aún no hay comentarios.