Suponha que eu estivesse usando sha1pass
para gerar um hash de alguma senha confidencial na linha de comando. Posso usar sha1pass mysecret
para gerar um hash de mysecret
mas isso tem a desvantagem que mysecret
agora está no histórico do bash. Existe uma maneira de atingir o objetivo final deste comando, evitando a revelação mysecret
em texto simples, talvez usando um passwd
prompt -style?
Também estou interessado em uma maneira generalizada de fazer isso para passar dados confidenciais para qualquer comando. O método mudaria quando os dados confidenciais fossem passados como um argumento (como em sha1pass
) ou em STDIN para algum comando.
Existe uma maneira de conseguir isso?
Edit : Esta questão atraiu muita atenção e várias boas respostas foram oferecidas abaixo. Um resumo é:
- De acordo com a resposta de @Kusalananda , idealmente, nunca seria necessário fornecer uma senha ou segredo como argumento de linha de comando para um utilitário. Isso é vulnerável de várias maneiras, conforme descrito por ele, e deve-se usar um utilitário melhor projetado que seja capaz de receber a entrada secreta no STDIN
- A resposta de @vfbsilva descreve como impedir que as coisas sejam armazenadas no histórico do bash
- A resposta de @Jonathan descreve um método perfeitamente bom para fazer isso, desde que o programa possa obter seus dados secretos no STDIN. Como tal, decidi aceitar esta resposta.
sha1pass
no meu OP foi apenas um exemplo, mas a discussão estabeleceu que existem ferramentas melhores que coletam dados no STDIN. - como @R.. observa em sua resposta , o uso de expansão de comando em uma variável não é seguro.
Portanto, em resumo, aceitei a resposta de @Jonathan, pois é a melhor solução, pois você tem um programa bem projetado e bem-comportado para trabalhar. Embora passar uma senha ou segredo como um argumento de linha de comando seja fundamentalmente inseguro, as outras respostas fornecem maneiras de mitigar as preocupações simples de segurança.
Idealmente, você nunca digita uma senha de texto não criptografado na linha de comando como um argumento para um comando. Fazer isso torna a senha um argumento para o comando, e os argumentos da linha de comando podem ser vistos na tabela de processos usando ferramentas simples como
ps
ou registrados em alguns logs de auditoria.Dito isto, certamente existem maneiras de ocultar a senha real do histórico de comandos do shell.
Em seguida, digite a senha e pressione Enter. O
head
comando usado aqui aceita exatamente uma linha de entrada e a última nova linha que você digitar não fará parte dos dados que são passados parasha1pass
.Para evitar que os caracteres ecoem:
O
stty -echo
comando desativa o eco dos caracteres digitados no terminal. O eco é então restaurado comstty echo
.Para transmitir a entrada padrão, esse último comando pode ser alterado (você teria feito isso se
sha1pass
aceitasse dados na entrada padrão, mas aparece como se este utilitário específico estivesse ignorando sua entrada padrão):Se você precisar de entrada de várias linhas (o acima assume que uma única linha deve ser passada, sem caractere de nova linha no final), substitua todo o
head
comandocat
e encerre a entrada (supondo quesomecommand
ele seja lido até o final do arquivo) com Ctrl+D( seguinte Returnse desejar incluir um caractere de nova linha na entrada ou duas vezes se não quiser).Isso funcionaria independentemente do shell que você estivesse usando (desde que fosse um shell do tipo Bourne ou rc).
Alguns shells podem ser feitos para não salvar os comandos digitados em seus arquivos de histórico se o comando for precedido por um espaço. Isso geralmente envolve ter que definir
HISTCONTROL
o valorignorespace
. Isso é suportado pelo menos porbash
eksh
no OpenBSD, mas não por, por exemplo,ksh93
oudash
.zsh
os usuários podem usar ahistignorespace
opção ou suaHISTORY_IGNORE
variável para definir um padrão a ser ignorado.Em shells que suportam leitura
read
sem ecoar caracteres para o terminal, você também pode usarmas isso obviamente ainda tem o mesmo problema com a revelação potencial da senha na tabela de processos.
Se o utilitário ler da entrada padrão e se o shell suportar "here-strings", o acima poderá ser alterado para
Resumo dos comentários abaixo:
A execução de um comando com uma senha fornecida na linha de comando, que todos os comandos acima fazem, exceto aquele que canaliza os dados para o comando, tornará a senha potencialmente visível para qualquer pessoa executando
ps
ao mesmo tempo. No entanto, nenhum dos comandos acima salvará a senha digitada no arquivo de histórico do shell se executado a partir de um shell interativo.Programas bem comportados que lêem senhas de texto não criptografado fazem isso lendo de sua entrada padrão, de um arquivo ou diretamente do terminal.
sha1pass
requer a senha na linha de comando, digitada diretamente ou usando alguma forma de substituição de comando.Se possível, use outra ferramenta.
Se você definir
HISTCONTROL
assim:e inicie o comando com um espaço:
não será armazenado no histórico.
Se estiver usando o shell
zsh
oubash
, use a opção -s para oread
shell integrado para ler uma linha do dispositivo terminal sem que ela seja repetida.Então você pode usar algum redirecionamento sofisticado para usar a variável como stdin.
Se alguém executar
ps
, tudo o que verá é "sha1pass".Isso pressupõe que
sha1pass
lê a senha do stdin (em uma linha, ignorando o delimitador de linha) quando não recebe nenhum argumento.Passe dados confidenciais por meio de um pipe ou here-doc:
ou:
É bom que os segredos estejam em variáveis de shell (não exportadas), mas você nunca pode usar essas variáveis em linhas de comando, apenas em here-documents e shell internals.
Conforme observado por Kusalananda em um comentário, se você estiver inserindo comandos em um shell interativo, as linhas inseridas para um documento here serão armazenadas no histórico do shell, portanto, não é seguro digitar uma senha lá, mas ainda deve ser seguro usar variáveis shell contendo segredos; o histórico conterá o texto
$secret
em vez de qualquer coisa$secret
expandida.O uso de expansões de comando não é seguro :
porque a saída será incluída na linha de comando e visível na
ps
saída (ou leitura manual de /proc), exceto em sistemas com /proc endurecido.A atribuição a uma variável também é aceitável:
Basta escrever o valor em um arquivo e passar o arquivo:
Não tenho certeza de como
sha1pass
funciona, se puder receber um arquivo como entrada, você pode usarsha1pass < mysecret
. Caso contrário, usarcat
pode ser um problema, pois inclui a nova linha final. Se for esse o caso, use (se o seuhead
suporte-c
):Se o que o terdon fez for possível, então essa é a melhor solução, passando pela entrada padrão. O único problema que resta é que ele escreveu a senha no disco. Podemos fazer isso em vez disso:
Como Kusalananda disse,
stty -echo
garante que o que você digita não seja visto até que você o façastty echo
novamente.head -1
obterá uma linha da entrada padrão e a passará parasha1pass
.eu usaria
cat
leria de stdin atéEOF
, o que pode ser causado pressionando Ctrl+D. Então, o resultado seria passado como argumento parasha1pass
Se você está passando informações confidenciais e as usa regularmente, provavelmente é melhor criptografá-las.
Colocando algo como
Em seu .bashrc, você terá uma variável de ambiente criptografada que você pode acessar sempre que precisar de um segredo, e será solicitada a senha/senha que você usou ao criar a variável de ambiente.
No exemplo acima é 'secret'
Você acessa é um comando da seguinte forma
por exemplo
Para sua consulta usando
sha1pass
. Você pode criar e passar da seguinte formaEntão use da seguinte forma
A parte base64 é para que você possa definir a variável
E não deixe seu segredo preso no histórico de comandos etc etc.
Quando você gera o segredo, às vezes, a saída base64 terá várias linhas, então você precisa fazer as quebras de linha para sua variável.
O openssh solicitará uma senha para criptografar e descriptografar a cada vez, você pode fornecer uma como parte do comando, mas estará apenas ocultando coisas do histórico, etc. Dê uma olhada em https://www.tecmint.com/ generate-encrypt-decrypt-random-passwords-in-linux/ para obter algumas informações sobre como usar o openssh para isso. https://www.serverlab.ca/tutorials/linux/administration-linux/how-to-base64-encode-and-decode-from-command-line/ para base64 e https://stackoverflow.com/questions/16072351 /how-to-assign-an-output-to-a-shellscript-variable para diferentes opções na substituição de comando que usei back-tick ` acima