En este post se describen una herramienta (git-crypt) y un grupo de prácticas y principios (el principio Castle Approach también conocido como Defensa en Profundidad) para incrementar la protección de datos dentro de un repositorio git (privado).

 

Introducción: repositorio git

Una vez hemos agotado alternativas mejores y más seguras, a veces deberemos guardar información secreta en un repositorio git. La manera manual de hacerlo sería encriptando/desencriptando la información usando GPG o Gnu Privacy Guard (ver esta guía), pero hay un método mejor: git-crypt.

 

¿Qué es git-crypt?

Git crypt es una solución que usa GPG por debajo y que permite encriptación transparente. Crea un vault con seguridad GPG.

En la web de su proyecto podemos leer:

Git-crypt permite la encriptación y desencriptación transparente de archivos en un repositorio git.

Los archivos que quieras proteger serán encriptados al hacer commit y desencriptados al hacer checkout.

Git-crypt te permite compartir libremente un repositorio que contenga contenido tanto público como privado.

git-crypt permite trabajar de manera transparente con el contenido desencriptado, de forma que desarrolladores que no tengan la clave secreta podrán clonar y hacer commit en un repositorio con archivos encriptados.

Esto te permite almacenar tu material secreto (como pueden ser claves o passwords) en el mismo repositorio que tu código sin tener que bloquearlo.

Solo un usuario autorizado puede dar permisos a otros usuarios. Si no fuera así, la seguridad sería inútil, pues podrías añadirte a cualquier vault.

 

Git-crypt: Cómo lo utilizo

Normalmente hago la separación que menciona el autor de git-crypt: algunas partes de mi repositorio son secretas, y en consecuencia deberán ser encriptadas.

Normalmente utilizo un nombre descriptivo para esta carpeta; prefiero mostrar mi carpeta con claves con el nombre “keys” que no aplicar el concepto de “Seguridad por Oscuridad” y poner, por ejemplo, “src/test/resources/selenium”.

Preparación

Preparar el repositorio git:

cd repo
git-crypt init

Especifica que carpetas/archivos deben ser encriptados, como git-filters:

$ cat .gitattributes
keys filter=git-crypt diff=git-crypt

Añade los usuarios autorizados (identificados por su clave GPG):

git-crypt add-gpg-user USER_ID

Uso

  • Clonar el repositorio
  • Desbloquear el vault: git-crypt unlock
  • Hacer los cambios seguido de un commit
  • Push
  • Esto deja el vault abierto en tu ordenador, pero no el remoto. Lo puedes cerrar mediante git-crypt lock. Dejarlo abierto o cerrado importa poco si un atacante puede sencillamente usar un comando para desbloquearlo (sin protección extra).

Flujos de trabajo comunes

  • En la máquina del desarrollador: Crea el vault, añádete como usuario fiable. Pide las claves públicas a los miembros de tu equipo y añádelas al vault.
  • En el entorno de Integración Continua (CI): Añade una clave GPG común para los ejecutores jenkins/CI. Autorízala en el repositorio.

Seguridad

Git-crypt usa GPG internamente, así que el nivel de seguridad debería ser el dado por GPG, a excepción de posibles errores en el propio programa git-crypt.

De la web del proyecto:

Git-crypt es más seguro que otros sistemas git de encriptación transparente. git-crypt encripta archivos usando AES-256 en modo CTR con un synthetic IV derivado del SHA-1 HMAC del archivo. Este modo de operar proporciona seguridad semántica ante CPAs (chosen-plain attacks) determinísticos. Esto significa que pese a que la encriptación es determinística (lo cual es requerido para que git pueda distinguir cuando un archivo ha cambiado y cuando no), no filtra información más allá de mostrar si dos archivos son idénticos o no. […]

 

Limitaciones y Trucos

Utilizar un repositorio público rompe el principio de Defensa en profundidad.

Debes ir con cuidado cuando añadas la clave al repositorio: podrías exponer tu email (por ejemplo, me@mydomain.com). Esto es un punto de entrada para ataques de phishing.

Cualquier usuario no autorizado puede ver que estamos usando git-crypt basándose en la evidencia dejada en el archivo .gitattributes:

Git-crypt no encripta nombres de archivo, mensajes de commit, symlink targets, gitlinks, u otros metadatos.

Otras preocupaciones relacionadas con la seguridad, del sitio web del proyecto:

Git-crypt se apoya en git filters, los cuales no fueron diseñados con la encriptación en mente. Así pues, git-crypt no es la mejor herramienta para encriptar la mayoría o totalidad de los archivos de un repositorio. Donde git-crypt destaca es en aquellos casos en que la mayoría del repositorio es público pero unos pocos archivos deben ser encriptados (por ejemplo, claves privadas o archivos con credenciales API). Para encriptar un repositorio entero, mejor considerar usar un sistema como git-remote-gcrypt. (Nota: no respondemos de la seguridad de git-remote-gcrypt).

Git-crypt no esconde cuando un archivo cambia o no, cuanto ocupa o el hecho de dos archivos sean idénticos.

Los archivos encriptados con git-crypt no se pueden comprimir. Incluso el más pequeño de los cambios en un archivo encriptado requiere que git archive el archivo modificado en su totalidad y no solo un delta.

A pesar de que git-crypt protege el contenido de los archivos individuales con SHA-1 HMAC, git-crypt no puede ser usado de forma segura a menos que el repositorio entero esté protegido contra la alteración de datos (un atacante que pueda mutar tu repositorio podrá alterar tu archivo .gitattributes para deshabilitar la encriptación). Si fuera necesario, usa características de git cómo signed tags en vez de contar únicamente con git-crypt para la integridad.

El diff del commit varía cuando el vault está abierto vs cuando está cerrado. Cuando está abierto, los contenidos del archivo están en formato plano, es decir, desencriptados. En consecuencia puedes ver el diff. Cuando el vault está cerrado, no se puede apreciar un diff efectivo ya que el texto cifrado cambia, pero el ojo humano no puede distinguir los contenidos.

Extras

Hay ocasiones en las que debemos utilizar secretos en nuestra aplicación. Puede ser por configuración de entorno (por ejemplo, credenciales de base de datos, servicios de los que dependemos) o por configuración de aplicación.

En un caso óptimo, esta información debería estar presente en alguna otra parte, separado del código fuente de la aplicación:

  • Principio de menor privilegio: los administradores tienen acceso a secretos, pero no al código, mientras que los desarrolladores tienen acceso al código pero no a los secretos (pueden tener acceso a secretos pre-prod)
  • La velocidad de cambio es distinta, siguiendo así el Principio de responsabilidad única de SOLID.

Principios

Seguimos los siguientes principios de “Security Principles we live by” (Howard02):

  • Usar Defensa en Profundidad
  • No Depender Solamente de Seguridad por Oscuridad

Sobre Defensa en Profundidad:

La idea principal detrás de la defensa en profundidad es gestionar el riesgo con distintas estrategias defensivas, así si una capa defensiva no es suficiente otra capa pueda prevenir una brecha completa. – (Howard02)

Sobre Seguridad por Oscuridad:

Asume siempre que un atacante sabe lo mismo que tú — asume que el atacante tiene acceso a todos los códigos fuente y todos los diseños. Incluso si no es así, es trivialmente fácil para un atacante determinar información oscurecida. […] La oscuridad es una defensa útil, siempre que no sea tu única defensa. En otras palabras, es válido usar la oscuridad como parte de una estrategia defensiva mucho mayor. – (Howard02)

Referencias y Enlaces

 

Apéndice

Los “Principios de seguridad que seguimos”

Esta es la lista completa con los principios de seguridad explicados en “Writing Secure Code”, por Howard y LeBlanc:

  • Aprender de los errores
  • Reduce Tu superficie de ataque
  • Emplea defaults seguros
  • Utiliza Defensa en Profundidad
  • Utiliza Menor Privilegio
  • La Retrocompatibilidad siempre te da dolores de cabeza
  • Asume que los Sistemas Externos son Inseguros
  • Planifica Fracasar
  • Fracasa de Modo Seguro
  • Recuerda que Características de Seguridad != Características Seguras
  • Nunca depender solamente de Seguridad por Oscuridad
  • No Mezcles Código e Información
  • Arregla los problemas de Seguridad Correctamente

(Lista original en Inglés):

  • Learn from Mistakes
  • Minimize Your Attack Surface
  • Employ Secure Defaults
  • Use Defense in Depth
  • Use Least Privilege
  • Backward Compatibility Will Always Give You Grief
  • Assume External Systems Are Insecure
  • Plan on Failure
  • Fail to a Secure Mode
  • Remember That Security Features != Secure Features
  • Never Depend on Security Through Obscurity Alone
  • Don’t Mix Code and Data
  • Fix Security Issues Correctly