Suponha que eu estivesse usando sha1pass
para gerar um hash de alguma senha confidencial na linha de comando. Eu posso usar sha1pass mysecret
para gerar um hash, mysecret
mas isso tem a desvantagem que mysecret
está agora no histórico do bash. Existe uma maneira de atingir o objetivo final deste comando, evitando revelar mysecret
em texto simples, talvez usando um passwd
prompt de estilo?
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 no STDIN para algum comando.
Existe uma maneira de conseguir isso?
Edit : Esta questão atraiu muita atenção e houve várias boas respostas oferecidas abaixo. Um resumo é:
- De acordo com a resposta de @ Kusalananda , o ideal seria nunca dar uma senha ou segredo como argumento da linha de comando a um utilitário. Isso é vulnerável de várias maneiras, conforme descrito por ele, e deve-se usar um utilitário melhor projetado, capaz de receber informações secretas sobre o STDIN
- A resposta de @ vfbsilva descreve como impedir que 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 levar seus dados secretos para o STDIN. Como tal, decidi aceitar esta resposta.
sha1pass
no meu PO era apenas um exemplo, mas a discussão estabeleceu que existem melhores ferramentas que utilizam dados no STDIN. - como @R .. observa em sua resposta , o uso da expansão de comando em uma variável não é seguro.
Então, em resumo, aceitei a resposta do @ Jonathan, já que é a melhor solução, pois você tem um programa bem projetado e comportado para trabalhar. Embora passar uma senha ou segredo como argumento da linha de comando seja fundamentalmente inseguro, as outras respostas fornecem maneiras de atenuar os simples problemas de segurança.
sha1pass mysecret
está sendo executado e, portanto, saber o quemysecret
é. (Isso só funciona para os poucos segundos enquanto o programa está sendo executado, é claro ...)Respostas:
Se estiver usando o
zsh
oubash
shell, use a opção -s noread
shell interno para ler uma linha do dispositivo terminal sem que ele ecoe.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 de stdin (em uma linha, ignorando o delimitador de linha) quando não recebe nenhum argumento.fonte
sha1pass
não usa seu fluxo de entrada padrão.sha1pass
foi apenas um exemplo no meu OP e claramente não é a melhor opção para isso.ps
, mas pode ser gravado em um arquivo temporário - se alguém quiser evitar isso,sshpass < <(printf '%s\n' "$VARIABLE")
pode ser considerado (porqueprintf
é um builtin, não um comando externo, não é passadoexecv
e acessível viaps
).Idealmente, você nunca digita uma senha de texto não criptografado na linha de comando como argumento para um comando. Isso faz da 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 registradas 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ê digita não fará parte dos dados transmitidossha1pass
.Para impedir que os caracteres ecoem:
O
stty -echo
comando desativa o eco dos caracteres digitados no terminal. O eco é então restaurado comstty echo
.Para passar a entrada padrão, esse último comando pode ser alterado (você o faria se os
sha1pass
dados aceitos na entrada padrão, mas parece que esse utilitário em particular está ignorando sua entrada padrão):Se você precisar de entrada com várias linhas (o que foi dito acima pressupõe que uma única linha deva ser transmitida, sem nenhum caractere de nova linha no final), substitua o
head
comando inteiro porcat
e encerre a entrada (supondo quesomecommand
ele leia até o final do arquivo) com Ctrl+D( a seguir, Returnse você deseja incluir um caractere de nova linha na entrada ou duas vezes, se não).Isso funcionaria independentemente de qual shell você estivesse usando (desde que fosse um shell tipo Bourne ou rc).
Alguns shells podem ser feitos para não salvar os comandos digitados nos 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 menosbash
eksh
no OpenBSD, mas não por exemploksh93
oudash
.zsh
os usuários podem usar ahistignorespace
opção ou suaHISTORY_IGNORE
variável para definir um padrão a ser ignorado.Nas conchas que suportam a leitura
read
sem ecoar caracteres no terminal, você também pode usarmas isso obviamente ainda tem o mesmo problema em potencialmente revelar a 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, como todos os comandos acima, exceto o que canaliza os dados para o comando, potencialmente tornará a senha visível para qualquer pessoa que esteja executando
ps
ao mesmo tempo. No entanto, nenhum dos comandos acima salvará a senha digitada no arquivo de histórico do shell se executada a partir de um shell interativo.Programas bem comportados que leem senhas em texto não criptografado fazem isso lendo suas entradas padrão, 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.
fonte
$(...)
fará parte da linha de comando e será visível naps
saída, exceto em um sistema com / proc.sha1pass
executar sem senha na linha de comando parece produzir uma saída sem ler nada ... Portanto, o OP precisa escolher uma ferramenta diferente.Se você definir
HISTCONTROL
assim:e inicie o comando com um espaço:
não será armazenado no histórico.
fonte
Passe dados confidenciais por um canal ou aqui-doc:
ou:
É bom que os segredos estejam em variáveis de shell (não exportadas), mas você nunca pode usá-las em linhas de comando, apenas em documentos aqui e em shell internals.
Como observado por Kusalananda em um comentário, se você estiver digitando comandos em um shell interativo, as linhas que você digitar para um documento aqui serão armazenadas no histórico do shell, portanto, não é seguro digitar uma senha lá, mas ainda deve ser seguro usar variáveis de shell contendo segredos; a história conterá o texto
$secret
e não o que for$secret
expandido.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 reforçado.A atribuição a uma variável também é aceitável:
fonte
command_with_secret_output
que me permita digitar a saída secreta. Existe um comando desse tipo que poderia ser substituído aqui?bash
sessão interativa salvará o documento no arquivo de histórico.read
, por exemploread -r secret
. Então seu segredo está aí$secret
. Você pode executar stty antes / depois para ocultar a entrada, se quiser.sha1pass
parece fundamentalmente quebrado / inutilizável / inseguro, pois não pode ler a senha do stdin ou de um arquivo. Um utilitário diferente é necessário para resolver o problema, eu acho.read -rs
vai fazer o trabalho (se você incluir-r
a ser capaz de ter senhas com barras invertidas em-los), mas então você está de volta ao potencialmente mostrando a senha na lista de processos (e consoante o processo de contabilidade está ligado e como isso é configurado , também nos registros contábeis do processo).Basta escrever o valor em um arquivo e passar o arquivo:
Não sei ao certo como
sha1pass
funciona; se ele pode receber um arquivo como entrada, você pode usá-losha1pass < mysecret
. Caso contrário, o usocat
pode ser um problema, pois inclui a nova linha final. Se for esse o caso, use (se o seuhead
suporte-c
):fonte
cat | sha1pass
?cat mysecret | sha1pass
esha1pass < mysecret
tem o mesmo comportamento em relação às novas linhas finais.cat
não adiciona novas linhas. De qualquer forma, se houversha1pass
suporte para passar a senha através da entrada padrão, eu esperaria que ela ignorasse a nova linha final sozinha. Arquivos com linhas que não são finalizadas por novas linhas não são naturais no unix, afinal, seria estranho esperar um arquivo que não seja finalizado por uma nova linha.cat | sha1pass
parece funcionarsha1pass
antes de me dar uma chance de inserir qualquer entrada. ii) Não, é clarocat mysecret
que não adiciona uma nova linha, eu nunca disse que acat
adiciona, apenas que a inclui .< mysecret
remove. :)head -c-1
. Acho que fiquei confuso sobre o porquê de usarcat mysecret | sha1pass
e depois proporsha1pass < mysecret
. Acho que a preocupação é que o sha1pass possa reclamar dos arquivos regulares do stdin; Não sei por que.sha1pass
e não consegui encontrar um manual ou-h
qualquer outra forma de documentação nos poucos minutos que passei pesquisando e, portanto, não consegui descobrir se a execução ésha1pass foo
tratadafoo
como uma string de entrada ou como um arquivo de entrada . Por isso, dei opções para lidar com cada possibilidade.Se o que o terdon fez é possível, essa é a melhor solução, passando pela entrada padrão. O único problema que resta é que ele escreveu a senha no disco. Em vez disso, podemos fazer isso:
Como Kusalananda disse,
stty -echo
garante que o que você digita não é visto até que você façastty echo
novamente.head -1
obterá uma linha da entrada padrão e a passará parasha1pass
.fonte
eu usaria
cat
leria de stdin atéEOF
, o que pode ser causado pressionando Ctrl + D. Em seguida, o resultado seria passado como argumento parasha1pass
fonte