bashでユーザー入力のパスワードをプログラムの標準入力の一部にする最も安全で簡単な方法は何ですか?


12

ユーザーにbashシェルプロンプトでパスワードを入力させ、そのパスワードをプログラムのstdinの一部にするための(1)最も安全で(2)最も簡単な方法を探しています。

:これが見えるようにstdinを必要とするもので{"username":"myname","password":"<my-password>"}<my-password>何をしているが、プロンプトシェルに入力されます。プログラムstdinを制御できれば、パスワードを安全に要求して設定できるようにプログラムを変更できますが、ダウンストリームは標準的な汎用コマンドです。

以下を使用するアプローチを検討し、拒否しました。

  • コマンドラインにパスワードを入力するユーザー:パスワードは画面に表示され、「ps」を介してすべてのユーザーに表示されます
  • 外部プログラムへの引数へのシェル変数補間(例:)...$PASSWORD...:パスワードは引き続き "ps"を介してすべてのユーザーに表示されます
  • 環境変数(環境に残っている場合):パスワードはすべての子プロセスに表示されます。信頼できるプロセスでさえ、診断の一部としてコアダンプまたは環境変数をダンプする場合、パスワードを公開する可能性があります
  • 長期間ファイルに保存されたパスワード、たとえ権限が厳しいファイルでも:ユーザーが誤ってパスワードを公開し、rootユーザーが誤ってパスワードを表示する可能性があります

私は現在の解決策を以下の答えとして挙げますが、誰かがそれを思いついた場合、より良い答えを喜んで選択します。もっと単純なもの、または誰かが私が見逃したセキュリティ上の懸念を見つけたのではないかと思います。


(完全な使用例は、パスワードがHTTPSサーバーへのPOSTの本文の一部である必要があることですが、この質問を過度に具体的にしたくありません。stdinはcurl "-d @ -"。)
ジムホーグランド

回答:


13

bashzsh

unset -v password # make sure it's not exported
set +o allexport  # make sure variables are not automatically exported
IFS= read -rs password < /dev/tty &&
  printf '{"username":"myname","password":"%s"}\n' "$password" | cmd

なしIFS=readは、入力したパスワードから先頭と末尾の空白が削除されます。

がなければ-r、バックスラッシュを引用文字として処理します。

ターミナルからのみ読み取ることを確認する必要があります。

echo確実に使用することはできません。ではbashzshprintfそのコマンドラインの出力に表示されないように、組み込みされますps

ではbash、引用符で囲む必要があります。$passwordそうでない場合は、split + glob演算子が適用されます。

その文字列をJSONとしてエンコードする必要があるので、それはまだ間違っています。たとえば、少なくとも二重引用符とバックスラッシュは問題になります。これらの文字のエンコードについて心配する必要があるでしょう。プログラムはUTF-8文字列を期待していますか?端末は何を送信しますか?

プロンプト文字列を追加するにはzsh

IFS= read -rs 'password?Please enter a password: '

bash

IFS= read -rsp 'Please enter a password: ' password

printf-これは、perlの呼び出しを回避するために必要なことです-良いヒントです。それはあなたが持っている良いですunset passwordし、set +aあなたは現在のシェルの詳細仮定を行うことができれば、それはスキップすることができても、そこに。IFS=さまざまなパスワードの一般性を高めるために-rオプションを読み取り、それを先行させるという利点。/ dev / ttyから端末への入力を強制するのに適しています。
ジムホーグランド

1
はい、まだ二重引用符とバックスラッシュに問題があります。JSONブロブの二重引用符で囲まれたフィールド内に配置する前に、これらをエンコードする必要があります。curlがUTF-8を想定しているかどうかは不明です。
Jim Hoagland

1
python3 -c 'import json; print(json.dumps({"username": "myname", "password": input()}))'、Pythonが横になっている場合。Python 2の場合、s / input / raw_input /。そのコマンドにパスワードをパイプすると、適切なJSONが出力されます。
Kevin

Kevin、パスワードをstdinに安全に取得でき、Pythonの起動を気にしないのであれば、これは良い提案です。これにより、オンザフライでJSONが構築されます。これは、Python内でgetpass.getpass()を使用するとうまく機能しますが、保存されたパスワードを繰り返し使用できなくなる可能性があります。
Jim Hoagland、2015年

2

これが私が持っている解決策です(テストされています):

$ read -s PASSWORD
<user types password>
$ echo -n $PASSWORD | perl -e '$_=<>; print "{\"username\":\"myname\",\"password\":\"$_\"}"'

説明:

  1. read -sstdin(パスワード)の行を画面にエコーせずに読み取ります。シェル変数PASSWORDに格納されます。
  2. echo -n $PASSWORD改行なしでパスワードをstdoutに書き込みます。(echoはシェルの組み込みコマンドなので、新しいプロセスは作成されないため、(AFAIK)echoの引数としてのパスワードはpsに表示されません。)
  3. perlが呼び出され、パスワードをstdinから $_
  4. perlはパスワードを$_全文に入力し、標準出力に出力します

これがHTTPS POSTの場合、2行目は次のようになります。

echo -n $PASSWORD | perl -e '$_=<>; print "{\"username\":\"myname\",\"password\":\"$_\"}"' | curl -H "Content-Type: application/json" -d@- -X POST <url-to-post-to>

3
これはかなりよさそうだ。perlを呼び出す理由はまったくないことに注意します。printf '{"username":"myname","password":"%s"}' $PASSWORD同じセキュリティプロパティを保持し、外部プロセスを節約するのようなものを完全に実行できます。
トム・ハント

2
read-sフラグをサポートしないコマンドのソリューションを一般化したい場合は、「stty -echo; read PASSWORD; stty echo」を使用できます
Jeff Schaller

2
パイプは、各サイドに1つずつ、合計2つの新しいプロセスを開始します。代わりにhere-stringを使用してくださいperl -e '...' <<< "$PASSWORD"
chepner

2
@chepner、<<<中にbash悪化している一時ファイルに格納したコンテンツ。
ステファンChazelas

1
TLDPによると、ファイルは作成されますが、他のプロセスからは読み取ることができません。「ここではドキュメントは一時ファイルを作成しますが、これらのファイルは開いた後に削除され、他のプロセスからアクセスできません。」例19-12の直後のtldp.org/LDP/abs/html/here-docs.html
dragon788 2017

0

のバージョンがをreadサポートしていない場合は-sこの回答にあるPOSIX互換の方法を試してください。

echo -n "USERNAME: "; read uname
echo -n "PASSWORD: "; set +a; stty -echo; read passwd; command <<<"$passwd"; set -a; stty echo; echo
passwd= # get rid of passwd possibly only necessary if running outside of a script

これset +aは、環境への変数の自動「エクスポート」を防ぐことになっています。のマニュアルページを確認してくださいstty。利用可能なオプションはたくさんあります。<<<"$passwd"適切なパスワードにはスペースを含めることができるため、これは引用されています。echoを有効にした後の最後stty echoは、次のコマンド/出力を新しい行で開始することです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.