É seguro usar o echo para passar dados confidenciais para o chpasswd?

16

Eu estou tentando definir em massa algumas senhas de conta de usuário usando chpasswd . As senhas devem ser geradas aleatoriamente e impressas em stdout (preciso anotá-las ou armazená-las em uma senha) e também passar para chpasswd .

Ingenuamente, eu faria isso assim

{
  echo student1:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
  echo student2:$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo '')
} | tee >(chpasswd)

No entanto, me preocupo em passar a nova senha como um argumento de linha de comando para echo , porque os argumentos geralmente são visíveis para outros usuários em ps -aux (embora nunca tenha visto nenhuma linha echo em ps ). / p>

Existe uma maneira alternativa de adicionar um valor à minha senha retornada e, em seguida, passá-la para chpasswd ?

    
por Nils Werner 02.08.2018 / 11:01

2 respostas

14

Seu código deve estar seguro, pois echo não aparecerá na tabela de processos, já que é um shell embutido.

Aqui está uma solução alternativa:

#!/bin/bash

n=20
paste -d : <( seq -f 'student%.0f' 1 "$n" ) \
           <( tr -cd 'A-Za-z0-9' </dev/urandom | fold -w 13 | head -n "$n" ) |
tee secret.txt | chpasswd

Isso cria os nomes e senhas de seus alunos, n deles, sem passar nenhuma senha em qualquer linha de comando de qualquer comando.

O utilitário paste cole vários arquivos como colunas e insere um delimitador entre eles. Aqui, usamos : como o delimitador e fornecemos dois "arquivos" (substituições de processo). O primeiro contém a saída de um comando seq que cria 20 nomes de usuários e o segundo contém a saída de um pipeline que cria 20 strings aleatórias de comprimento 13.

Se você tiver um arquivo com nomes de usuário já gerados:

#!/bin/bash

n=$(wc -l <usernames.txt)

paste -d : usernames.txt \
           <( tr -cd 'A-Za-z0-9' </dev/urandom | fold -w 13 | head -n "$n" ) |
tee secret.txt | chpasswd

Isso salvará as senhas e nomes de usuários no arquivo secret.txt em vez de mostrar as senhas geradas no terminal.

    
por 02.08.2018 / 11:35
8
É muito provável que o

echo esteja incorporado ao shell, por isso não apareceria em ps como um processo separado.

Mas você não precisa usar a substituição de comando, você pode simplesmente ter a saída do pipeline diretamente para chpasswd :

{  printf "%s:" "$username";
   head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13 ; echo ''
} | chpasswd 

Se você quiser alterar várias senhas com uma execução de chpasswd , deve ser fácil repetir as partes essenciais. Ou faça isso em uma função:

genpws() {
    for user in "$@"; do
        printf "%s:" "$user";
        head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13
        echo
    done
}
genpws username1 username2... | chpasswd 

Como um aparte: head /dev/urandom parece um pouco estranho, pois urandom não é orientado a linhas. Ele pode ler quantidades excessivas de bytes, o que afetará a noção do kernel de entropia disponível, o que, por sua vez, pode levar a /dev/random de bloqueio. Pode ser mais limpo apenas ler uma quantidade fixa de dados e usar algo como base64 para converter os bytes aleatórios em caracteres imprimíveis (em vez de apenas jogar fora cerca de 3/4 dos bytes que você obtém).

Algo como isso lhe daria aprox. 16 caracteres e números:

head -c 12 /dev/urandom | base64 | tr -dc A-Za-z0-9 

(isto é, 16 menos a quantidade de + e / caracteres na saída de base64 . A chance de qualquer um é de 1/32 por caractere, então se eu tiver a minha combinatória correta, isso dá aproximadamente 99% de chance de deixar pelo menos 14 caracteres e 99,99% de chance de deixar pelo menos 12.

    
por 02.08.2018 / 11:30