web-dev-qa-db-ja.com

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

私はbashスクリプトを作成しており、ユーザーにパスワードを要求してopensslに渡す必要があります。 opensslはパスワード自体を読み取ることができますが、プログラムを2回実行する必要があり、ユーザーに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インスタンスにパスワードを安全に渡すにはどうすればよいですか?

21
user14284

入力とは別のファイル記述子でパスワードを渡します(2回、暗号化と復号化に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を使用するには、Bash組み込みexecコマンドを使用して、いわゆるhere文字列をファイル記述子に関連付けることにより、printf '%s\n' "$PASS"を使用せずに実行できます。

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

(

# 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

)
8
jon

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

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

Hereドキュメントを使用すると、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
1
bsd