Ocultando senha em scripts de shell

23

Como ocultar uma senha nos scripts de shell? Há vários scripts que estão acessando o banco de dados. Se abrirmos o script, outros também saberão o nome de usuário e a senha. Então, se alguém souber se esconder, por favor me avise.

Eu tenho uma maneira: coloque a senha em um arquivo e torne o arquivo oculto e ninguém acessará o arquivo (altere as permissões e use o arquivo no script ao acessar o banco de dados).

uma corrida
fonte

Respostas:

35

Primeiro , como várias pessoas já disseram, é essencial manter as credenciais separadas do script. (Além do aumento da segurança, também significa que você pode reutilizar o mesmo script para vários sistemas com credenciais diferentes.)

Segundo , você deve considerar não apenas a segurança das credenciais, mas também o impacto se / quando essas credenciais forem comprometidas. Você não deve ter apenas uma senha para todo o acesso ao banco de dados, deve ter credenciais diferentes com diferentes níveis de acesso. Você pode, por exemplo, ter um usuário de banco de dados com capacidade de realizar uma pesquisa no banco de dados - esse usuário deve ter acesso somente leitura. Outro usuário pode ter permissão para inserir novos registros, mas não para excluí-los. Um terceiro pode ter permissão para excluir registros.

Além de restringir as permissões para cada conta, você também deve ter restrições sobre onde cada conta pode ser usada. Por exemplo, a conta usada pelo servidor da web não deve ter permissão para conectar-se a partir de nenhum outro endereço IP que não seja o do servidor da web. Uma conta com permissões de root completas para o banco de dados deve ser muito restrita, em termos de onde pode se conectar e nunca deve ser usada além de interativamente. Considere também o uso de procedimentos armazenados no banco de dados para restringir exatamente o que pode ser feito por cada conta.

Essas restrições precisam ser implementadas no lado do servidor DB do sistema, para que, mesmo que o lado do cliente esteja comprometido, as restrições não possam ser alteradas. (E, obviamente, o servidor do banco de dados precisa ser protegido com firewalls etc., além da configuração do banco de dados ...)

No caso de uma conta de banco de dados que tenha acesso limitado somente leitura limitado e apenas de um endereço IP específico, talvez você não precise de mais credenciais além disso, dependendo da sensibilidade dos dados e da segurança do host do script está sendo executado. Um exemplo pode ser um formulário de pesquisa em seu site, que pode ser executado com um usuário que só pode usar um procedimento armazenado que extrai apenas as informações que serão apresentadas na página da web. Nesse caso, adicionar uma senha realmente não confere nenhuma segurança extra, pois essas informações já devem ser públicas e o usuário não pode acessar outros dados que seriam mais sensíveis.

Verifique também se a conexão com o banco de dados é feita usando TLS, ou qualquer pessoa que esteja ouvindo na rede pode obter suas credenciais.

Terceiro , considere que tipo de credencial usar. As senhas são apenas uma forma e não as mais seguras. Você poderia usar alguma forma de par de chaves pública / privada, ou AD / PAM ou algo semelhante.

Quarto , considere as condições sob as quais o script será executado:

Se for executado interativamente, você deverá digitar a senha ou a senha da chave privada ou da chave privada ou efetuar login com um tíquete Kerberos válido ao executá-lo - em outras palavras, o script deve ter sua senha credenciais diretamente de você no momento em que você a executa, em vez de lê-las em algum arquivo.

Se for executado a partir de um servidor da web, considere configurar as credenciais no momento em que você iniciar o servidor da web. Um bom exemplo aqui são os certificados SSL - eles têm um certificado público e uma chave privada, e a chave privada tem uma senha. Você pode armazenar a chave privada no servidor da web, mas ainda precisa inserir a senha quando iniciar o Apache. Você também pode ter as credenciais em algum tipo de hardware, como um cartão físico ou um HSM, que podem ser removidos ou bloqueados quando o servidor é iniciado. (Obviamente, a desvantagem desse método é que o servidor não pode reiniciar por conta própria se algo acontecer. Eu preferiria isso ao risco de comprometer meu sistema, mas sua milhagem pode variar ...)

Se o script estiver sendo executado no cron, essa é a parte mais difícil. Você não quer ter as credenciais espalhadas por qualquer lugar do sistema onde alguém possa acessá-las - mas você deseja tê-las por aí para que seu script possa acessá-las, certo? Bem, não está bem. Considere exatamente o que o script está fazendo. De que permissões ele precisa no banco de dados? Pode ser restrito para que não importe se a pessoa errada se conectar com essas permissões? Em vez disso, você pode executar o script diretamente no servidor do banco de dados ao qual mais ninguém tem acesso, e não no servidor que possui outros usuários? Se, por algum motivo em que não consigo pensar, você absolutamente deve ter o script em execução em um servidor inseguro e deve ser capaz de fazer algo perigoso / destrutivo ... agora é um bom momento para repensar sua arquitetura.

Quinto , se você valoriza a segurança do seu banco de dados, não deve executar esses scripts em servidores aos quais outras pessoas tenham acesso. Se alguém estiver conectado ao seu sistema, ele poderá acessar suas credenciais. Por exemplo, no caso de um servidor da web com um certificado SSL, há pelo menos uma possibilidade teórica de alguém conseguir obter root e acessar a área de memória do processo httpd e extrair as credenciais. Nos últimos tempos, houve pelo menos uma exploração em que isso poderia ser feito por SSL, sem exigir que o invasor estivesse conectado.

Considere também usar o SELinux ou o apparmor ou o que estiver disponível para o seu sistema para restringir quais usuários podem fazer o que. Eles permitirão que você não permita que os usuários tentem se conectar ao banco de dados, mesmo que eles consigam obter acesso às credenciais.

Se tudo isso parece um exagero para você , e você não pode pagar ou não tem tempo para fazê-lo - então, na minha opinião (arrogante e elitista), você não deve armazenar nada importante ou sensível em seu banco de dados. E se você não está armazenando nada importante ou sensível, o local onde você armazena suas credenciais também não é importante; nesse caso, por que usar uma senha?

Por fim , se você absolutamente não puder evitar o armazenamento de algum tipo de credencial, poderá ter as credenciais somente leitura e pertencer a raiz e raiz poderá conceder propriedade em uma base extremamente temporária quando solicitado a fazê-lo por um script (porque seu script não deve ser execute como root, a menos que seja absolutamente necessário, e a conexão com um banco de dados não o torna necessário). Mas ainda não é uma boa ideia.

Jenny D
fonte
9
Não é arrogante e elitista. Ou então eu também estou. "Como posso proteger minhas jóias no caso de um ladrão invadir?" "Coloque-o em um cofre que seja parafusado / soldado no lugar." "Isso é demais, vou pegar um cofre portátil e pendurar a chave no gancho." "Então não se preocupe em usar um cofre." Conselho eminentemente sensato.
Curinga
12

Primeiro, se houver alguma maneira de alterar as coisas para evitar armazenar uma senha dentro ou ao lado de um script, você deve fazer todos os esforços para fazer isso. A resposta de Jenny D contém muitos bons conselhos para esse efeito.

Caso contrário, sua idéia de colocar a senha em um arquivo separado com permissões restritas é praticamente isso. Você pode, por exemplo, obter esse arquivo do script principal:

. /usr/local/etc/secret-password-here

Você também pode restringir as permissões do script principal para que apenas pessoas autorizadas possam executá-lo, mas provavelmente é melhor fazer o que você sugere e armazenar apenas a senha em um arquivo restrito. Dessa forma, você pode permitir a inspeção do próprio código (sem segredos sensíveis), o controle de versão e a cópia do script com mais facilidade, etc ...

Celada
fonte
@BasileStarynkevitch ah, mas vejo que também diz " /usr/local/etcpode ser um link simbólico para /etc/local". Eu senti falta disso. Então você também está certo, mas é um MAIO, portanto é opcional. Mas sim, isso não importa muito, e preferência pessoal.
28615 Celada
1
Só que eu estou fazer cópia de backup /etc/ , mas não /usr/local/ (que eu suponho que pode ser reconstruído após falha de disco)
Basile Starynkevitch
ponto justo sobre backups
Celada
3

Outras respostas abordaram o como , mas vou considerar o se . Dependendo do tipo de banco de dados ao qual os usuários estão se conectando, talvez você já tenha um mecanismo adequado que já seja usado por esses programas clientes; nesse caso, certifique-se de usá-los (estou pensando em ~/.mysqlrcou ~/.pgpass).

Se você está dando a vários usuários a capacidade de acessar o banco de dados para fazer consultas específicas usando uma conta compartilhada, provavelmente não deve. Em vez disso, verifique se eles têm contas no banco de dados e se essas contas não têm mais permissões do que precisam (provavelmente leia sobre muito disso e muito pouco acesso de gravação). Se eles precisarem fazer consultas específicas em determinadas tabelas às quais não podem acessar, forneça procedimentos armazenados SECURTY DEFINERpara permitir que eles façam isso.

Se nenhum dos evita acima de você que precisam armazenar credenciais, em seguida, leia as outras respostas aqui.

Toby Speight
fonte
1

Sua idéia de ocultar a senha em um local inacessível pode ser boa, dependendo das circunstâncias.

Se as informações estiverem separadas, isso significa que a edição simples do arquivo, por exemplo, durante uma revisão de código com um colega, não será exibida. Mas saiba que qualquer pessoa com acesso à sua conta pode encontrar facilmente esse arquivo. Eu usei um subdiretório ~/.sshpara esses fins, pelo simples motivo de sshqueixa se os direitos de acesso ~/.sshnão forem suficientemente restritos.

No entanto, existem outras coisas que você pode fazer para evitar esse olhar de nome de usuário e / ou senhas.

Ofuscação : Se você não deseja que ninguém leia o nome de usuário ou a senha enquanto edita um script, pode colocá-lo no texto, mas não como texto simples, mas ofuscado. Se a versão ofuscada for longa o suficiente para impedir sua memorização por alguém olhando para ela, ela não poderá ser conhecida, mesmo que o método e a chave de descriptografia estejam à vista. Obviamente, isso ainda seria trivialmente contornado por alguém que tenha acesso à sua conta.

Usando GPG :

Um pouco melhor, mas ainda não totalmente à prova de ataques do usuário root no seu sistema, é criptografar pares de nome de usuário / senha em um arquivo de seu gpgpúblico e fazer com que o script recupere o conteúdo do arquivo (possível solicitar uma senha, caso contrário em cache / expirado). Uso o ggp-card para que, quando deixo meu laptop por perto, mas puxo o cartão, não seja possível acessar mesmo que o pino ainda esteja em cache. Pelo menos se eu corro 20 vezes em poucos minutos, tenho que fornecer o pino apenas uma vez.

A segurança parece sempre inversamente relacionada à conveniência (configuração e uso).

Anthon
fonte
0

Existe uma maneira de armazenar senhas em um script bash, mas você precisa criptografar e ofuscar o script para que ninguém possa lê-lo ou executar qualquer tipo de depurador para ver exatamente o que está fazendo. Para criptografar e ofuscar um script bash / shell e fazer com que ele seja realmente executável, tente copiar e colar aqui:

http://www.kinglazy.com/shell-script-encryption-kinglazy-shieldx.htm

Na página acima, tudo o que você precisa fazer é enviar seu script (você pode enviar um exemplo de script primeiro para sua tranquilidade). Um arquivo zip será gerado para você. Clique com o botão direito do mouse no link de download e copie o URL fornecido. Em seguida, vá para sua caixa UNIX e execute as seguintes etapas.

Instalação:

  1. wget link para o arquivo zip

  2. descompacte o arquivo zip recém-baixado

  3. cd / tmp / KingLazySHIELD

  4. ./install.sh / var / tmp / KINGLAZY / SHIELDX- (seu-script-name) / home / (seu-username) -force

O que o comando de instalação acima fará por você é:

  1. Ele instalará a versão criptografada do seu script no diretório / var / tmp / KINGLAZY / SHIELDX- (nome do seu script).

  2. Ele colocará um link para esse script criptografado no diretório que você especificar em substituição de / home / (seu nome de usuário) - dessa forma, permitirá que você acesse facilmente o script sem precisar digitar o caminho absoluto.

  3. Garante que ninguém possa modificar o script - Qualquer tentativa de modificar o script criptografado o tornará inoperante ... até que essas tentativas sejam interrompidas ou removidas. Pode até ser configurado para notificá-lo sempre que alguém tentar fazer algo com o script, exceto executá-lo ... ou seja, tentativas de hacking ou modificação.

  4. Garante absolutamente NINGUÉM pode fazer cópias dele. Ninguém pode copiar seu script para um local isolado e tentar mexer com ele para ver como funciona. Todas as cópias do script devem ser links para o local original especificado durante a instalação (etapa 4).

NOTA:

Não acredito que isso funcione para scripts interativos que solicitam uma resposta ao usuário. Os valores devem ser codificados no script. A criptografia garante que ninguém possa realmente ver esses valores; portanto, você não precisa se preocupar com isso.

AncientMinds
fonte
0

Outra solução, sem levar em conta a segurança (também acho melhor manter as credenciais em outro arquivo ou em um banco de dados) é criptografar a senha com gpg e inseri-la no script.

Eu uso um par de chaves gpg sem senha que guardo em um usb. (Nota: Ao exportar esse par de chaves, não use --armor, exporte-o em formato binário).

Primeiro criptografe sua senha:

echo -n "pAssw0rd" | gpg --armor --no-default-keyring --keyring /media/usb/key.pub --recipient someone@mail.com --encrypt

Isso imprimirá a senha criptografada gpg na saída padrão. Copie a mensagem inteira e adicione-a ao script:

password=$(gpg --batch --quiet --no-default-keyring --secret-keyring /media/usb/key.priv --decrypt <<EOF 
-----BEGIN PGP MESSAGE-----

hQEMA0CjbyauRLJ8AQgAkZT5gK8TrdH6cZEy+Ufl0PObGZJ1YEbshacZb88RlRB9
h2z+s/Bso5HQxNd5tzkwulvhmoGu6K6hpMXM3mbYl07jHF4qr+oWijDkdjHBVcn5
0mkpYO1riUf0HXIYnvCZq/4k/ajGZRm8EdDy2JIWuwiidQ18irp07UUNO+AB9mq8
5VXUjUN3tLTexg4sLZDKFYGRi4fyVrYKGsi0i5AEHKwn5SmTb3f1pa5yXbv68eYE
lCVfy51rBbG87UTycZ3gFQjf1UkNVbp0WV+RPEM9JR7dgR+9I8bKCuKLFLnGaqvc
beA3A6eMpzXQqsAg6GGo3PW6fMHqe1ZCvidi6e4a/dJDAbHq0XWp93qcwygnWeQW
Ozr1hr5mCa+QkUSymxiUrRncRhyqSP0ok5j4rjwSJu9vmHTEUapiyQMQaEIF2e2S
/NIWGg==
=uriR
-----END PGP MESSAGE-----
EOF)

Dessa maneira, somente se o usb estiver montado no sistema, a senha poderá ser descriptografada. Obviamente, você também pode importar as chaves para o sistema (menos seguro ou sem segurança) ou pode proteger a chave privada com senha (para que não possa ser automatizada).

Juanu
fonte
-2
#!/bin/bash
unset username
unset password
unset dbname
echo -n "username:"
read username
echo -n "dbname:"
read dbname
prompt="password:"

    while IFS= read -p "$prompt" -r -s -n 1 char
            do
                    if [[ $char == $'\0' ]]
                            then
                                    break
                    fi
                    prompt='*'
                    password+="$char"
            #       read -s -p "Enter Password: "  pswd
            #       echo -e "\nYour password is: " $pswd
            done
uma corrida
fonte
3
Recuei seu código, talvez você possa explicar o que está tentando fazer?
Archemar 26/06
-6

Eu não acredito que você deva armazenar a senha. Não consigo pensar em uma única boa razão para isso. Em vez disso, você deve armazenar um hash salgado dessa senha - uma string que é produzida de forma confiável por alguma função quando a senha original é passada como entrada, mas nunca a senha .

mikeserv
fonte
5
Não sei ao certo como isso resolverá o problema de: a) poder se conectar a um serviço que exige uma senha eb) os usuários poderem ver o script e, assim, descobrir os detalhes da autenticação, sejam essas senhas ou não
Jenny D
1
Você está reivindicando saber minha resposta antes que eu a escreva.
Jenny D
1
Eu escrevi minha resposta agora. O que eu estava tentando obter de você era em parte o meu quinto ponto - uma vez que as credenciais são armazenadas na memória, elas não ficam totalmente seguras contra um invasor com acesso ao servidor. Além disso, sua resposta concisa não foi muito útil, embora não esteja incorreta. Estou pensando em apontando para ele na próxima vez que alguém reclamar que a ServerFault não são tão agradáveis como as pessoas em Unix / Linux :-)
Jenny D
2
@ JennyD - uma vez que o cred está na memória - certamente não precisa ficar lá - e essa é uma boa razão para lidar com hashes de qualquer maneira. Ainda assim, representarei alegremente os padrões de cortesia da comunidade como seu exemplo geral - sou muito conhecido por essa característica, de fato.
mikeserv
4
Após a sua grande discussão, gostaria de mencionar caso haja algum mal-entendido de que fui eu quem votou mal, não Jenny. E o motivo não era uma opinião sobre se é uma boa ideia usar um certificado e uma chave privada ou senha digitada interativamente ou fazer o que o OP queria ou o que quer. Isso ocorreu porque a resposta está errada: armazenar um hash salgado da senha como credencial do cliente não é uma coisa: hashes salgados são algo que você mantém no final da conexão que está verificando a autenticação, não no lado que está enviando.
28915 Celada