Como não senhas em scripts Python



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 :

  1. Roube o próprio código (fácil)
  2. Desobstruir, se necessário (fácil)

Ao usar um chaveiro local, um invasor precisa:

  1. Roube o próprio código (fácil)
  2. Desobstruir, se necessário (fácil)
  3. 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(): # ,       -  db_name = 'very_important_db' db_host = '147.237.0.71' passwd = keyring.get_password(systemname, username) print('Connecting to db: {}'.format(db_name)) print('Using very secret password from vault: {}'.format(passwd)) print('Doing something important...') print('Erasing the database...') print('Task completed') #    systemname = 'important_database' username = 'meklon' args = parse_arguments() #    ,    --newpass if args.newpass: #      CLI password = getpass.getpass(prompt="Enter secret password:") #       try: keyring.set_password(systemname, username, password) except Exception as error: print('Error: {}'.format(error)) #          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 :

 #      CLI password = getpass.getpass(prompt="Enter secret password:") 

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 .... 

Source: https://habr.com/ru/post/pt435652/


All Articles