È sicuro usare l'eco per trasferire dati sensibili in chpasswd?


17

Sto cercando di impostare in serie alcune password dell'account utente utilizzando chpasswd. Le password devono essere generate in modo casuale e stampate su stdout(ho bisogno di scriverle o metterle in un archivio di password) e anche passarle chpasswd.

Ingenuamente, lo farei così

{
  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)

Tuttavia, mi preoccupo di passare la nuova password come argomento a riga di comando echo, poiché gli argomenti sono di solito visibili ad altri utenti ps -aux(anche se non ho mai visto echoapparire alcuna riga ps).

Esiste un modo alternativo di anteporre un valore alla mia password restituita e poi passarlo in chpasswd?


6
echoè una shell integrata. Non verrebbe visualizzato nella tabella dei processi.
Kusalananda

Risposte:


15

Il codice dovrebbe essere sicuro in quanto echonon verrà visualizzato nella tabella dei processi poiché è una shell integrata.

Ecco una soluzione 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

Questo crea i nomi e le password ndei tuoi studenti, di essi, senza passare alcuna password su qualsiasi riga di comando di qualsiasi comando.

L' pasteutilità incolla diversi file come colonne e inserisce un delimitatore tra di essi. Qui, usiamo :come delimitatore e diamo due "file" (sostituzioni di processo). Il primo contiene l'output di un seqcomando che crea 20 nomi utente studente e il secondo contiene l'output di una pipeline che crea 20 stringhe casuali di lunghezza 13.

Se hai già un file con nomi utente già generati:

#!/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

Questi salveranno le password e i nomi utente nel file secret.txtinvece di mostrare le password generate nel terminale.


2
Questa è una soluzione intelligente che non ha bisogno echoo printf, tuttavia il codice è un po 'scomodo da decifrare
Nils Werner,

@NilsWerner Aggiunta una spiegazione in più. Fammi sapere se c'è una cosa particolare su cui vorresti che mi espandessi.
Kusalananda

1
echoTuttavia, non dovresti fare affidamento sul fatto di essere una shell integrata. Sulla maggior parte delle shell lo è, ma non è assolutamente necessario che lo sia.
Austin Hemmelgarn,

1
@Kusalananda Solo curioso, c'è una differenza effettiva tra tee secret.txt > >(chpasswd)e tee secret.txt | chpasswd? Quest'ultimo sembra molto più comune, quindi mi chiedo perché hai scelto di utilizzare la sostituzione di processo invece di una semplice pipe
Christopher Shroba,

1
@ChristopherShroba Nessun motivo diverso da quello è simile al codice che era già nella domanda (usando una sostituzione di processo con tee). Ora che l'hai sottolineato, penso che lo cambierò davvero (sembra migliore). Grazie.
Kusalananda

8

echoè molto probabilmente integrato nella shell, quindi non apparirebbe pscome un processo separato.

Ma non è necessario utilizzare la sostituzione dei comandi, puoi semplicemente avere l'output dalla pipeline direttamente a chpasswd:

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

Se si desidera modificare più password con una sola esecuzione chpasswd, dovrebbe essere facile ripetere le parti essenziali. O trasformalo in una funzione:

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 

A parte questo: head /dev/urandomsembra strano perché urandomnon è orientato alla linea. Potrebbe leggere una quantità eccessiva di byte, il che influenzerà la nozione di entropia disponibile del kernel, che a sua volta potrebbe portare al /dev/randomblocco. Potrebbe essere più semplice leggere una quantità fissa di dati e usare qualcosa di simile base64per convertire i byte casuali in caratteri stampabili (invece di buttare via circa 3/4 dei byte che ottieni).

Qualcosa del genere ti darebbe circa. 16 caratteri e numeri:

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

(vale a dire 16 in meno la quantità +e i /caratteri nell'output di base64. La possibilità di entrambi è 1/32 per carattere, quindi se ho la mia combinazione combinatoria giusta, ciò dà circa il 99% di possibilità di lasciare almeno 14 caratteri, e una probabilità del 99,99% di lasciare almeno 12.)


La tua printfsoluzione non fa quello che fa il mio codice originale: restituisce più righe per più nomi utente, ma apprezzo le tue osservazioni suhead urandom
Nils Werner,

@NilsWerner, beh, ho ritenuto evidente l'espansione a più utenti. Ma non importa, potremmo creare una funzione per produrre il nome utente: coppie di password per più utenti in una volta sola. (vedi modifica)
ilkkachu,

3
Non puoi davvero fare affidamento sulle prime 10 "linee" di urandom che contengono abbastanza dei personaggi che desideri. Invece, esegui urandom direttamente attraverso tr.
Kusalananda

@Kusalananda, intendi la mia head -c 10 | base64pipeline o quella di Nils head | tr? È probabile che 10 "linee" di byte casuali siano centinaia di byte (dato che solo 1 su 256 sarebbe newline), anche se in teoria potrebbe essere esattamente 10 byte, ma le probabilità sono completamente trascurabili. Allo stesso modo quando si usa base64, se i byte casuali dicono solo \xff, allora il base64 sarà solo una serie di barre, ma è anche abbastanza improbabile. Se ti interessa, puoi leggere più di 10 byte, ridurre le probabilità di ciò e quindi tagliare la lunghezza dell'output risultante.
ilkkachu,

1
@ilkkachu Mi riferisco ad entrambi i codici. Se leggi byte casuali e desideri qualcosa di una lunghezza particolare dopo aver filtrato ciò che non vuoi, non tagliare l'origine dati fino a quando non sei sicuro di aver ottenuto ciò di cui hai bisogno. Come dici tu, è molto improbabile che tu ottenga una stringa di dieci newline /dev/urandom, ma il rischio non è dello 0%.
Kusalananda
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.