任意のコマンドに対して、プロンプトを使用して機密データをbashで渡す方法はありますか?


40

sha1passコマンドラインで機密性の高いパスワードのハッシュを生成するために使用していたとします。のsha1pass mysecretハッシュを生成するために使用できますmysecretが、これにmysecretは現在bash履歴にある欠点があります。mysecretおそらくpasswd-styleプロンプトを使用して、プレーンテキストでの表示を回避しながら、このコマンドの最終目標を達成する方法はありますか?

また、機密データをコマンドに渡すためにこれを行う一般的な方法にも興味があります。メソッドは、機密データが引数(inなど)として、sha1passまたはSTDINで何らかのコマンドに渡されると変更されます。

これを達成する方法はありますか?


編集:この質問は多くの注目を集めており、いくつかの良い答えが下に提供されています。要約は次のとおりです。

  • あたりとしてKusalanandaの答え@、理想的には、ユーティリティのコマンドライン引数としてパスワードや秘密を与える必要はないだろう。これは彼が説明したようにいくつかの点で脆弱であり、STDINで秘密の入力を取得できる、より良く設計されたユーティリティを使用する必要があります。
  • @vfbsilvaの答えは、bashの履歴に物事が保存されるのを防ぐ方法を説明しています
  • @Jonathanの答えは、プログラムがSTDINでその秘密データを取得できる限り、これを達成するための完全に良い方法を説明しています。そのため、この答えを受け入れることにしました。sha1pass私のOPでは例に過ぎませんが、STDINでデータを取得するより優れたツールが存在するという議論が確立されました。
  • @R ..内のノート彼の答えは、変数のコマンド拡張を使用することであるない安全。

要約すると、適切に設計され、適切に動作するプログラムがあることを考えると、@ Jonathanの回答が最良のソリューションであるため、@ Jonathanの回答を受け入れました。コマンドライン引数としてパスワードまたはシークレットを渡すことは基本的に安全ではありませんが、他の答えは単純なセキュリティ上の懸念を軽減する方法を提供します。


6
それだけではありません:実行中のプロセスを一覧表示する権限を持つ同じマシン上の誰でも、実行中のプロセスを潜在的に見ることsha1pass mysecretができるため、何mysecretが起こっているかを知ることができます。(もちろん、プログラムが実際に実行されている間、これは数秒間しか機能しません...)
MathematicalOrchid

@MathematicalOrchidこれは、プライベート仮想マシンで実行することで回避できます。しかし、それは1つのパスワードのみを生成するように設定するには手間がかかりすぎるかもしれません... :-)
Kusalananda

5
@Kusalananda私のポイントは、「コマンド履歴をオフにする方法を見つけたとしても、コマンドラインに機密データを配置しないでください」ということでした...
MathematicalOrchid

2
ご存知のように、SHA-1はキーハッシュまたはパスワードハッシュではかなりの数年前から非推奨になっています。
デビッドフォースター

2
システムが監査デーモンを実行している場合、すべてのユーザーによるすべてのコマンドとすべての引数はrootによって一元的に記録されるため、これらのログにアクセスできる人は誰でもこれを見ることに注意してください。
ランドール

回答:


20

使用している場合zshbashシェルを、-sオプションを使用しread、それをエコーせずに、端末機器から行を読み取るためにシェル組み込み。

IFS= read -rs VARIABLE < /dev/tty

次に、いくつかの派手なリダイレクトを使用して、変数をstdinとして使用できます。

sha1pass <<<"$VARIABLE"

誰かが実行した場合ps、表示されるのは「sha1pass」だけです。

これは、sha1pass引数が指定されていない場合、stdinから(行区切り文字を無視して1行で)パスワードを読み取ることを前提としています。


sha1pass標準入力ストリームを使用しないことを確立したと思います。
クサラナナンダ

@Kusalanandaわかりましたが、この方法は標準入力から読み取るプログラムで機能します。
ジョナサン

だから、ユーティリティがSTDINで秘密の入力を受け取ることができると仮定すると、これはセキュリティ上健全で安全なソリューションですか?
記念

この答えを受け入れることにしました。それは、うまく動作するように設計されたプログラムがあること考えると、それが最良のソリューションだからです。sha1pass私のOPの単なる例であり、これに使用するのに最適な選択肢ではないことは明らかです。
18

1
@cemulate、... コマンドラインでは安全ではありません。heredocまたはherestringのコンテキストでは(ここの答えのように)、には公開されませんpsが、一時ファイルに書き込まれる場合あります-それを避けたい場合は、sshpass < <(printf '%s\n' "$VARIABLE")考慮される可能性があります(printf組み込みではなく、外部コマンド、それはに渡されずexecv、アクセスできませんps)。
チャールズダフィー

35

理想的には、コマンドの引数としてコマンドラインに平文のパスワードを入力しないでください。これを行うと、パスワードがコマンドの引数になり、コマンドライン引数は、psいくつかの監査ログなどの単純なツールを使用してプロセステーブルに表示される場合があります。

そうは言っても、実際のパスワードをシェルのコマンド履歴から隠す方法は確かにあります。

sha1pass "$( head -n 1 )"

次に、パスワードを入力してを押しEnterます。headここで使用するコマンドは、1つの入力のラインとあなたに渡されるデータの一部ではありません入力することを最後に改行を受け入れますsha1pass

文字がエコーしないようにするには:

sha1pass "$( stty -echo; head -n 1; stty echo )"

このstty -echoコマンドは、端末で入力された文字のエコーをオフにします。エコーはその後で復元されstty echoます。

標準入力を渡すために、その最後のコマンドを変更することができます(sha1pass標準入力でデータを受け入れた場合はこれを実行しますが、この特定のユーティリティは標準入力を無視しているように見えます)。

{ stty -echo; head -n 1; stty echo; } | somecommand

あなたは複数行の入力が必要な場合は、全体の置き換え(上記の一行が終わりなし改行文字で、合格しなければならないと仮定し)headでコマンドをcat入力を終了する(と仮定somecommandして、それ自体は、ファイルの終わりまで読み込み)Ctrl+DReturn入力に改行文字を含める場合は以下を、そうでない場合は2回)。

これは、使用しているシェルに関係なく機能します(Bourneのようなシェルまたはrcのようなシェルである限り)。

一部のシェルでは、コマンドの前にスペースが付いている場合、入力したコマンドを履歴ファイルに保存しないようにできます。これには通常HISTCONTROL、値を設定する必要がありますignorespace。これは、少なくともによってサポートされているbashkshOpenBSDの上ではなく、例えばによりますksh93dashzshユーザーはhistignorespaceオプションまたはHISTORY_IGNORE変数を使用して、無視するパターンを定義できます。

read端末に文字をエコーせずに読み取りをサポートするシェルでは、次も使用できます。

IFS= read -rs password     # -s turns off echoing in bash or zsh
                           # -r for reading backslashes as-is,
                           # IFS= to preserve leading and trailing blanks
sha1pass "$password"

しかし、これには明らかに、プロセステーブルでパスワードを明らかにする可能性があるという同じ問題があります。

ユーティリティが標準入力から読み取り、シェルが「here-strings」をサポートしている場合、上記を次のように変更できます。

IFS= read -rs password
somecommand <<<"$password"

以下のコメントの要約:

  • コマンドラインで指定されたパスワードを使用してコマンドを実行すると、データをコマンドにパイプするコマンドを除き、上記のすべてのコマンドでパスワードpsが同時に実行される可能性があります。ただし、上記のコマンドはいずれも、対話型シェルから実行された場合、入力されたパスワードをシェルの履歴ファイルに保存しません。

  • 平文パスワードを読み取る適切に動作するプログラムは、標準入力、ファイル、または直接端末から読み取ることにより、平文パスワードを読み取ります。

  • sha1pass 直接入力するか、何らかの形式のコマンド置換を使用して、コマンドラインでパスワードを要求します。

  • 可能な限り、別のツールを使用してください。


11
これは間違っています。コマンド拡張の結果は$(...)、コマンドラインの一部であり、ps/ procが強化されたシステムを除き、出力に表示されます。
R ..

3
@Kusalananda、開始後にargvを上書きしても、上書きが行われる前に脆弱なウィンドウが残ります。これは緩和策であり、修正ではありません。
チャールズダフィー

5
@Kusalananda、パスワードをハッシュするための適切に設計されたプログラムはコマンドラインでの入力を必要としないため、条件付きは基本的に与えられます- そうでない場合は、別のツールを選択する必要があります。
チャールズダフィー

4
@CharlesDuffy:ここのツールは根本的に壊れているようです。sha1passコマンドラインでパスワードなしで実行すると、何も読み込まずに出力が生成されるようです...したがって、OPは別のツールを選択する必要があります。
R ..

8
この答えはセキュリティの観点からは安全ではなく、唯一の利点はパスワードがシェル履歴に表示されないことですが、その利点はコマンドの前にスペースを含めることで簡単に達成できます
Ferrybig

25

そのように設定した場合HISTCONTROL

HISTCONTROL=ignorespace

そして、スペースでコマンドを開始します:

~$  mycommand

履歴には保存されません。


10

パイプまたはhere-docを介して機密データを渡します。

command_with_secret_output | command_with_secret_input

または:

command_with_secret_input <<EOF
$secret
EOF

シークレットが(エクスポートされていない)シェル変数にあることは問題ありませんが、コマンドラインでこれらの変数を使用することはできません。ヒアドキュメントとシェル内部でのみ使用できます。

Kusalanandaがコメントで述べたように、インタラクティブシェルでコマンドを入力している場合、ヒアドキュメントに入力した行はシェル履歴に保存されるため、そこにパスワードを入力するのは安全ではありませんが、秘密を含むシェル変数を使用しても安全です。履歴には、展開された$secretものではなくテキストが含まれます$secret

コマンド展開の使用は安全ではありません

command_with_secret_input "$(command_with_secret_output)"

これは、出力がコマンドラインに含まれ、ps/ procが強化されたシステムを除き、出力に表示される(または/ procから手動で読み取る)ためです。

変数への代入も大丈夫です:

secret=$(command_with_secret_output)

私が探しているのは、秘密の出力command_with_secret_output入力できる実際のコマンドです。ここで置き換えることができるコマンドはありますか?
記念

対話型bash セッションでヒアドキュメントを入力すると、履歴ファイルにドキュメントが保存されることに注意してください。
クサラナナンダ

@cemulate:シェル組み込みコマンドを使用するだけですread(例:)read -r secret。それからあなたの秘密はにあり$secretます。必要に応じて、その前後にsttyを実行して、入力を非表示にすることができます。
R ..

3
@Kusalananda:sha1passstdinまたはファイルからパスワードを読み取れないため、基本的に壊れている/使用できない/安全でないようです。この問題を解決するには、別のユーティリティが必要だと思います。
R ..

1
@cemulate Rへの最後のコメントはまさにその場にあります。それが役に立たない理由です。read -rs-rバックスラッシュを含むパスワードを含めることができる場合)ジョブを実行しますが、プロセスリストでパスワードを表示する可能性があります(プロセスアカウンティングがオンになっているかどうかとその設定に応じて、プロセスアカウンティングログでも同様です)。
クサラナナンダ

6

値をファイルに書き込み、ファイルを渡すだけです。

$ cat > mysecret
Big seecreeeet!
$ cat mysecret | sha1pass 

どのようにsha1pass機能するかわかりませんが、入力としてファイルを取得できる場合は、を使用できますsha1pass < mysecret。そうでない場合cat、最後の改行が含まれるため、使用が問題になる可能性があります。その場合は、使用します(headサポートしている場合-c):

head -c-1 mysecret | sha1pass 

2
最初の例でパスワードをディスクに書き込むのはなぜcat | sha1passですか?cat mysecret | sha1passそしてsha1pass < mysecret、最終的な改行に関して同じ動作をします。cat改行を追加しません。とにかく、sha1pass標準入力を介したパスワードの受け渡しをサポートしている場合、それ自体で最終改行を無視することを期待します。改行で終わらない行を含むファイルは、結局unixでは不自然なので、改行で終わらないファイルを期待するのは厄介です。
-JoL

@JoL i)私はそれを考えていなかったので:/しかし、それはどのように機能するのでしょうか?入力を入力する機会を与える前cat | sha1passに実行されるようsha1passです。ⅱ)いや、もちろんcat mysecret改行を追加しません、私が言ったことはありませんcat、それは唯一のこと、それを追加含まれて。
テルドン

わかりましたが、< mysecretそれも削除するようなものではありません。:)
JoL

気にしないで。読み直しましたが、後で提案することを言ったことがわかりますhead -c-1。私はなぜ使用してからcat mysecret | sha1pass提案するのかについて混乱したと思いsha1pass < mysecretます。心配は、sha1passがstdinの通常のファイルについて文句を言うかもしれないことだと思います。理由はわかりません。
-JoL

@JoLそれは私が使ったsha1passことがないので、-h検索に費やした数分でマニュアルやその他のドキュメントを見つけることができなかったため、入力文字列または入力ファイルとしてsha1pass foo処理さfooれているかどうかがわかりませんでした。したがって、私はそれぞれの可能性に対処するためのオプションを提供しました。
テルドン

1

terdonがしたことが可能であれば、それが標準入力を通過する最良のソリューションです。残った唯一の問題は、彼がパスワードをディスクに書き込んだことです。代わりにこれを行うことができます:

stty -echo
echo -n "password: "
head -1 | sha1pass
stty echo

Kusalanandaが言ったstty -echoように、あなたがタイプしたものはあなたがstty echo再びするまで見られないことを保証します。head -1は、標準入力から1行を取得してに渡しsha1passます。


0

私は使うだろう

sha1pass "$(cat)"

catEOFCtrl + Dを押すと、stdinまで読み取ります。次に、結果が引数として渡されますsha1pass


3
R ..の答えは、なぜこれが安全でないのかを説明しています。
hvd
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.