Sichere Möglichkeit, Passwort für> 1 Programme in der Bash zu übergeben

21

Ich schreibe ein bashSkript und muss den Benutzer nach seinem Passwort fragen und es an weitergeben openssl. Während opensslich das Passwort selbst lesen kann, benötige ich für zwei Programmläufe und möchte den Benutzer nicht zweimal fragen. Hier ist das Skript:

cp file{,.old}
read -sp 'Enter password. ' PASS; echo
export PASS

# decode | edit | encode
openssl enc -d -aes-256-cbc -k "$PASS" -in file.old | \
  sed ... | openssl enc -e -aes-256-cbc -k "$PASS" -out file

unset PASS

Dies ist nicht sicher, da das Kennwort in der Befehlszeile leicht verfügbar ist. jemand kann es pszum Beispiel lesen .

openssllesen kann ein Passwort aus einer Umgebungsvariablen, so dass ich ersetzen kann -k "$PASS"mit -pass env:PASS, aber es ist noch nicht sicher; Die Umgebungsvariablen jedes Prozesses können frei gelesen werden ( pskönnen es wieder tun).

Wie kann ich das Kennwort sicher an die beiden opensslInstanzen übergeben?

Chris Down
quelle
Eine Kombination aus GnuPG und PinEntry kann hier verwendet werden. gnupg.org/related_software/pinentry/index.de.html
Nikhil Mulley
"Die Umgebungsvariablen eines Prozesses können frei gelesen werden" - das ist nicht ganz richtig. psLiest die Umgebung eines Prozesses aus /proc/<pid>/environ, diese Datei verfügt jedoch über 0600Berechtigungen, sodass nur Root und der Benutzer, der den Prozess ausführt, die Umgebung des Prozesses lesen können. Ich würde sagen, das ist ziemlich sicher.
Martin von Wittich

Antworten:

16

Übergeben Sie das Kennwort in einem von der Eingabe getrennten Dateideskriptor (zweimal, einmal zur Verschlüsselung und einmal zur Entschlüsselung). Nicht PASSin die Umwelt exportieren .

read -sp 'Enter password. ' PASS
printf '%s\n' "$PASS" |
openssl enc -d -aes-256-cbc -kfile /dev/stdin -in file.old |
sed ... | {
  printf '%s\n' "$PASS" |
  openssl enc -e -aes-256-cbc -kfile /dev/stdin -in /dev/fd/3 -out file;
} 3<&0

Wenn Ihr System nicht über Folgendes verfügt /dev/fd, können Sie mit dem -passArgument angeben openssl, dass die Passphrase aus einem geöffneten Dateideskriptor gelesen werden soll.

printf '%s\n' "$PASS" | {
  printf '%s\n' "$PASS" |
  openssl enc -d -aes-256-cbc -pass fd:0 -in file.old |
  tr a-z A-Z | tee /dev/tty | {
  openssl enc -e -aes-256-cbc -pass fd:3 -out file; }
} 3<&0
Gilles 'SO - hör auf böse zu sein'
quelle
Wie ich aus einer anderen Antwort verstehe , ist die bashVersion mit auch env:PASSsicher.
printf '%s\n' "$PASS"ist nicht sicher. Jemand kann pszum Beispiel die Kommandozeile lesen .
6
@ user14284 Nein und nein. env:PASSist nicht sicher, da das Kennwort in der Umgebung des opensslProzesses angezeigt würde (es würde nicht in der Umgebung des bashProzesses angezeigt, aber das ist nicht genug). Verwenden printfist sicher, weil es eine eingebaute Bash ist.
Gilles 'SO - hör auf böse zu sein'
Echo ist eine eingebaute Bash. Wäre ein einfacher Echo-Befehl also nicht sicher? echo $PASS | openssl .... Es würde nicht in der ps-Liste erscheinen. Der einzige Ort, den Sie passieren können, ist der Bash-Prozess-Speicher. Ich glaube ?
Gaoithe
1
@gaoithe Ja, echowäre aus dem gleichen Grund printfsicher, ist sicher (und printfwäre nicht sicher in einer Shell, in der es nicht eingebaut ist). Der Grund, den ich benutze printfund nicht, echoist, dass echoBackslashes (abhängig von den Bash-Optionen) beschädigt werden können.
Gilles 'SO - hör auf böse zu sein'
8

Bei der Verwendung von Bash kann auf die Verwendung verzichtet werden, printf '%s\n' "$PASS"indem den Dateideskriptoren mithilfe des integrierten execBefehls Bash ein sogenannter Here-String zugeordnet wird .

Weitere Informationen finden Sie unter: Sicherheit von Shell-Skriptkennwörtern für Befehlszeilenparameter .

(

# sample code to edit password-protected file with openssl
# user should have to enter password only once
# password should not become visible using the ps command

echo hello > tmp.file

#env -i bash --norc   # clean up environment
set +o history
unset PASS || exit 1

read -sp 'Enter password. ' PASS; echo

# encrypt file and protect it by given password
exec 3<<<"$PASS"
openssl enc -e -aes-256-cbc -pass fd:3  -in tmp.file -out file

cp file{,.old}

# decode | edit | encode
exec 3<<<"$PASS" 4<<<"$PASS"
openssl enc -d -aes-256-cbc -pass fd:3 -in file.old | 
   sed 's/l/L/g' | 
   openssl enc -e -aes-256-cbc -pass fd:4 -out file

exec 3<<<"$PASS"
openssl enc -d -aes-256-cbc -pass fd:3 -in file

rm -P tmp.file file.old
unset PASS

)
jon
quelle
1

Entschuldigung, meine vorherige Antwort stammte von openssl man, nicht von openssl enc docs.

Diese Lösung ist keine Pipeline, aber ich glaube, diese Lösung verhindert, dass das Passwort für ps sichtbar wird.

Bei Verwendung eines Here-Dokuments sieht nur openssl den Text des Passworts.
Solange Sie sicher sind, dass Sie die Zwischendatei entfernen, bleibt keine Spur zurück. Vielleicht kann jemand helfen, dies in einer Pipeline zu tun und die Zwischendatei zu beseitigen?

# cp file{,.old}  don't need this anymore since intermediate becomes same
read -sp 'Enter password. ' PASS; echo
#no need to export, env's are readable, as mentioned

# decode into intermediate file
openssl <<HERE 2>&1 >/dev/null
enc -d -aes-256-cbc -k "$PASS" -in file -out intermediate
HERE

# edit intermediate

# encode intermediate back into file
openssl <<HERE 2>&1 >/dev/null
enc -e -aes-256-cbc -k "$PASS" -in intermediate -out file 
HERE
unset PASS
rm -f intermediate
bsd
quelle
Dies ist eine bessere Antwort, wenn die Verwendung des Schalters erläutert wird. Es ist nicht falsch (außer dass der encBefehl keinen -knSchalter hat, zumindest in den aktuellen Versionen -pass), aber nicht sehr informativ. (Die Gegenstimme ist nicht meine.)
Gilles 'SO - hör auf, böse zu sein'
Danke @Gilles, schaute auf die Dokumente und sah meinen Fehler, aktualisierte Antwort mit einem anderen Ansatz.
bsd