
Manter senhas sempre foi uma dor de cabeça. Na versão clássica, você tem um usuário que está se esforçando muito para não esquecer o terrivelmente secreto “qwerty123” e o sistema de informações que armazena o hash dessa senha. Um bom sistema também resolve cuidadosamente hashes para envenenar a vida de pessoas más que podem roubar um banco de dados com senhas com hash. Tudo está claro aqui. Algumas senhas são armazenadas na cabeça e outras são criptografadas no keepass.
Tudo muda quando removemos do esquema uma pessoa que digita cuidadosamente a chave de um pedaço de papel. Na interação de dois sistemas de informação, em qualquer caso, a senha deve ser armazenada no lado do cliente em um formulário aberto para o sistema, para que possa ser transmitida e comparada com o hash de referência. E, nesse estágio, os administradores geralmente abrem a filial local de uma fábrica de bicicletas e começam a esconder, ofuscar e enterrar cuidadosamente a chave secreta no código do script. Muitas dessas opções não são apenas inúteis, mas também perigosas. Vou tentar oferecer uma solução conveniente e segura para esse problema para python. E um pequeno toque no PowerShell.
Como não fazer
Todos estão familiarizados com o conceito de "script temporário". Aqui, literalmente, apenas os dados podem ser analisados rapidamente do banco de dados e excluídos. E, de repente, acontece que o script já migrou para a zona de desenvolvimento em algum lugar da produção. E então começam a surgir surpresas desagradáveis da “descartabilidade” inicial.
A opção mais comum é no estilo de:
db_login = 'john.doe' password = 'password!'
O problema é que aqui a senha brilha claramente e é facilmente detectada entre os depósitos de scripts antigos pela pesquisa automática. Uma versão um pouco mais complicada segue o caminho da segurança através da obscuridade, com a senha armazenada em uma forma criptografada diretamente no código. Nesse caso, a descriptografia de volta deve ser realizada imediatamente, caso contrário, o cliente não poderá apresentar essa senha ao lado do servidor. Esse método salvará o máximo de uma aparência casual, mas qualquer análise séria do código manualmente permitirá que você extraia facilmente a chave secreta. O código abaixo salvará apenas os "surfistas do ombro":
>>> import base64 >>> print base64.b64encode("password") cGFzc3dvcmQ= >>> print base64.b64decode("cGFzc3dvcmQ=") password
O cenário mais desagradável é o uso de sistemas de controle de versão, como o git, para esses arquivos com informações confidenciais. Mesmo que o autor decida limpar todas as senhas, elas permanecerão no histórico do repositório. De fato, se você executar um arquivo com dados secretos no git, poderá considerá-los automaticamente comprometidos e iniciar imediatamente o procedimento para substituir todas as credenciais afetadas.
Usando o armazenamento do sistema
Há uma biblioteca de
chaveiros legal. O princípio básico de operação é baseado no fato de que cada usuário do sistema operacional possui seu próprio armazenamento criptografado, cujo acesso é possível somente após o usuário efetuar login no sistema. É multiplataforma e usará o back-end para armazenar senhas fornecidas pelo sistema operacional:
- KDE4 e KDE5 KWallet (é necessário dbus)
- Serviço Secreto Freedesktop - muitos DEs, incluindo GNOME (requer armazenamento secreto)
- Armário de credenciais do Windows
- Chaveiro macOS
Você também pode usar
backends alternativos ou escrever seus próprios, se for absolutamente necessário algo estranho.
Comparar dificuldade de ataque
Ao armazenar a senha diretamente no script, você precisa :
- Roube o próprio código (fácil)
- Desobstruir, se necessário (fácil)
Ao usar um chaveiro local, um invasor precisa:- Roube o próprio código (fácil)
- Desobstruir, se necessário (fácil)
- Para comprometer a máquina local efetuando login como usuário atacado (difícil)
Teoricamente, o acesso ao armazenamento local pode ser obtido por qualquer programa local em execução em nome do usuário atual, se ele souber as configurações de acesso para a senha secreta. No entanto, isso não é um problema, pois, no caso de uma conta comprometida, um invasor poderá interceptar todos os dados confidenciais. Outros usuários e seus softwares não terão acesso ao keystore local.
Exemplo de uso
import argparse import getpass import keyring def parse_arguments(): parser = argparse.ArgumentParser() parser.add_argument("-n", "--newpass", required=False, help="Set new password", action="store_true") arguments = parser.parse_args() return arguments def fake_db_connection():
Senha de Segurança
Outro vazamento de senha secreta comum é o histórico da linha de comando. O uso de entrada padrão não é permitido aqui:
age = input("What is your age? ") print "Your age is: ", age type(age) >>output What is your age? 100 Your age is: 100 type 'int'>
No exemplo acima, eu já mencionei a biblioteca
getpass :
A inserção de dados ao usá-los é semelhante à abordagem clássica * nix no login. Os dados não são gravados ou exibidos em nenhuma tela nos logs do sistema.
Um pouco sobre o PowerShell
Para o Powershell, a opção certa é usar o Windows Credential Locker padrão.
Isso é implementado pelo módulo
CredentialManager .
Exemplo de uso:
Install-Module CredentialManager -force New-StoredCredential -Target $url -Username $ENV:Username -Pass .... Get-StoredCredential -Target ....