GH Actions - Cache Poisoning
Cache Poisoning
Usar la acción de Git action/cache en cualquier parte del CI ejecutará dos pasos: un paso tendrá lugar durante el proceso de ejecución cuando se llama y el otro tendrá lugar después del workflow (si la acción de ejecución devolvió un cache-miss).
Acción de ejecución – se utiliza para buscar y recuperar la caché. La búsqueda se realiza utilizando la clave de caché, con el resultado siendo un cache-hit (éxito, datos encontrados en caché) o cache-miss. Si se encuentra, los archivos y directorios se recuperan de la caché para su uso activo. Si el resultado es cache-miss, los archivos y directorios deseados se descargan como si fuera la primera vez que se llaman.
Acción post workflow – se utiliza para guardar la caché. Si el resultado de la llamada a la caché en la acción de ejecución devuelve un cache-miss, esta acción guardará el estado actual de los directorios que queremos cachear con la clave proporcionada. Esta acción ocurre automáticamente y no necesita ser llamada explícitamente.
Las restricciones de acceso proporcionan aislamiento de caché y seguridad al crear un límite lógico entre diferentes ramas (por ejemplo: una caché creada para la rama Feature-A [con la base principal] no sería accesible para un pull request para la rama Feature-B [con la base principal]).
La acción de caché primero busca aciertos de caché para una clave y restaura claves en la rama que contiene la ejecución del workflow. Si no hay aciertos en la rama actual, la acción de caché busca la clave y restaura claves en la rama padre y ramas ascendentes.
El acceso a una caché está limitado por rama (actual y padre), lo que significa que se proporciona acceso a todos los workflows a través de ejecuciones de dicha rama.
Otra nota importante es que GitHub no permite modificaciones una vez que las entradas son empujadas – las entradas de caché son registros de solo lectura.
Usamos un ejemplo de CI que incluía dos workflows. Este ejemplo muestra cómo un ataque puede pivotar de un workflow de permisos bajos a uno de permisos altos.
Workflow de unit-test ejecutando herramientas de pruebas unitarias y cobertura de código. Suponemos que una de las herramientas es maliciosa o vulnerable a la ejecución de código remoto. El workflow no necesita usar la acción de Git action/cache. Cualquier workflow puede acceder a la caché.
Workflow de release construye y libera el artefacto de la aplicación. Este workflow utiliza una caché para optimizar el uso de las dependencias de Golang.
El workflow de unit-test utiliza una acción maliciosa que añade una entrada de caché con contenido malicioso cambiando una biblioteca de registro de Golang (go.uber.org/zap@v1) para añadir la cadena, 'BAD library' a la descripción del artefacto de la aplicación.
A continuación, el workflow de release utiliza esta entrada de caché envenenada. Como resultado, el código malicioso se inyecta en el binario de Golang construido y en la imagen. La caché permanece envenenada hasta que se descarta la clave de entrada (normalmente desencadenado por actualizaciones de dependencias). La misma caché envenenada afectará a cualquier otro workflow, ejecución y rama hija que utilice la misma clave de caché.
En la prueba que realizamos, logramos inyectar la cadena 'BAD library' en la descripción de la imagen:
Esto fue en la versión 0.4.1. A continuación, actualizamos la etiqueta y reconstruimos la imagen varias veces, y observamos que 'Bad library' permanecía en la descripción.
Esta técnica fue tomada de https://scribesecurity.com/blog/github-cache-poisoning/
Last updated