bashで1つ以上のプログラムのパスワードを渡す安全な方法


21

bashスクリプトを書いているので、ユーザーにパスワードを要求してに渡す必要がありますopenssl。なくなりopensslパスワード自体を読むことができ、私はプログラムの2つの実行のために必要と二回ユーザーに依頼する必要はありません。スクリプトは次のとおりです。

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

パスワードはコマンドラインを見ると簡単に入手できるため、これは安全ではありません。psたとえば、誰かがそれを使用して読むことができます。

openssl環境変数からパスワードを読み取ることができますので、私は置き換えることができ-k "$PASS"-pass env:PASS、それはまだ安全ではありません。任意のプロセスの環境変数は自由に読み取ることができます(繰り返しpsます)。

それでは、どうすれば2つのopensslインスタンスにパスワードを安全に渡すことができますか?


GnuPGのとPinEntryの組み合わせここで使用することができgnupg.org/related_software/pinentry/index.en.html
ニキルMulley

「プロセスの環境変数は自由に読み取ることができます」-これは完全に正しいわけではありません。psからプロセスの環境を読み取り/proc/<pid>/environますが、このファイルには0600アクセス許可があるため、プロセスを実行しているのはrootとユーザーのみです。それはかなり安全だと思います。
マーティンフォンウィティッヒ

回答:


16

入力とは別のファイル記述子でパスワードを渡します(2回、暗号化のために1回、復号化のために1回)。PASS環境にエクスポートしないでください。

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

システムにがない場合/dev/fdは、-pass引数を使用してopenssl、開いているファイル記述子からパスフレーズを読み取るように指示できます。

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

からあなたの答えを理解するように、bashバージョンでenv:PASSは、も安全です。

printf '%s\n' "$PASS"安全ではありません。psたとえば、誰かがコマンドラインを読むことができます。

6
@ user14284いいえ、いいえ。env:PASSパスワードはopensslプロセスの環境に表示されるため、安全ではありません(プロセスの環境には表示されませんがbash、それだけでは不十分です)。printfbashが組み込まれているため、使用は安全です。
ジル 'SO-悪である停止

echoはbashが組み込まれているので、単純なechoコマンドは安全ではないでしょうか?echo $PASS | openssl ...。psリストには表示されません。パスを取得できる唯一の場所は、bashプロセスメモリ内です。おもう ?
gaoithe

1
@gaoitheはい、echo同じ理由printfで安全です(printf組み込まれていないシェルでは安全ではありません)。私が使用printfしていないのechoは、echoバックスラッシュを壊す可能性があるためです(bashオプションによって異なります)。
ジル「SO-悪であるのをやめる」

8

Bashを使用printf '%s\n' "$PASS"すると、Bhere組み込みexecコマンドを使用して、いわゆるhereストリングをファイル記述子に関連付けることにより、使用せずに実行できます。

詳細については、「コマンドラインパラメータのシェルスクリプトパスワードセキュリティ」を参照してください。

(

# 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

)

1

申し訳ありませんが、以前の回答はopenssl enc docsではなくopenssl manからでした。

このソリューションはパイプラインではありませんが、このソリューションはパスワードがpsに見えないようにするものと思います。

ヒアドキュメントを使用すると、opensslのみがパスワードのテキストを参照できます。
中間ファイルを確実に削除する限り、トレースは残りません。たぶん誰かがパイプラインでこれを行い、中間ファイルを排除するのを助けることができますか?

# 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

スイッチの使用方法を説明している場合、これはより良い答えになります。それは間違っていません(少なくとも現在のバージョンではencコマンドに-knスイッチがないことを除いて-pass)が、あまり有益ではありません。(downvoteは私のものではありません。)
ジル「SO-悪であるのをやめる」

@Gillesに感謝し、ドキュメントを見て、私の失敗を見て、別のアプローチで答えを更新しました。
-bsd
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.