SSHを介して他のサーバーと通信する必要があるデータベースベースのアプリケーションがあります。 Webアプリケーションは、鍵ペアを生成し、ユーザーに公開鍵を提供したり、Webフォームフィールドで暗号化されていない秘密鍵を許可したりできます。その後、復号化可能な暗号化を使用して鍵を暗号化し、データベースに保存します。
WebアプリケーションがSSHサーバーと通信するときは、秘密鍵を復号化して何らかの方法でSSHに提供する必要があります。安全な一時ファイルを作成し、mktemp
sshを介してファイルを指定してファイルを削除できますが、これは追加の操作であり、新しい方法でキーを公開するため、必要ありません。man ssh
, , を見てみましたが、man ssh-agent
キーman ssh-add
を最初にファイルに追加せずに使用できる方法がないようです。私は何を見逃していますか?
答え1
ssh
/ etcなどの既存のツールを使用するには、ssh-agent
ファイルにキーを提供する必要があります。
別の、おそらくより実現可能なソリューションは、ssh
アプリケーションで直接クライアントを実装し、サードパーティのライブラリに依存することです。クリップシュまたは、ssh
/を展開してssh-agent
データベースから直接キーを受信して復号化することもできます。
答え2
ファイルは、アプリケーション間でデータを交換する主な手段です。ディスクファイルである必要はありません。一時記憶域のファイルまたはパイプである可能性があります。ssh-add
キーファイルがパスワードで保護されていない限り、キーファイルを標準入力に提供できます(キーファイルは暗号化されて保存されるため、パスワードで保護する理由はありません)。
/run
または、複雑な作業を行わないでください(/dev/shm
または/tmp
ディストリビューションで提供されているすべてのもの)、などのメモリ対応ファイルシステムにファイルを書き込みます。
または、外部暗号化なしで秘密鍵ファイルを保持しますが、パスワードを設定してください。ランダムに生成された長いパスワードを使用し、そのパスワードをデータベースに保存します。
1実験的にパスワードssh-add
で保護されており、検索できないキーファイル(名前付きパイプなど)がブロックされます。
答え3
申し訳ありません。答えではありませんが、コメントが長すぎてそのコメントが正しいと思いました。
重要なのは、暗号化された鍵をデータベースに保存することで達成することです。
一時秘密鍵ファイルへのアクセス権を持つ攻撃者は、SSHクライアントプロセスのメモリを読み取ることもできます(したがって、とにかくキーデータを取得する可能性があります)。どちらのデータも本質的に同じアクセス権を持つ必要があるためです。つまり、ファイルを隠そうとします。うまくいかないようです。より安全になりません。
データベース、Webアプリケーション、およびSSH接続に異なるユーザーを使用している場合は、データベースにキーを保存し、Webアプリケーションから復号化してSSHに提供するだけで、プロセス全体で鍵が伝播されます。ベクトル。 1人のユーザーだけを使用してこれらすべてのタスク(db、app、ssh)を実行すると、コードが複雑になります。
唯一の利点は、システムを他のホストに簡単に移動でき、データベースデータが盗まれたが、Webアプリケーション(暗号解読アルゴリズムとパスワードを含むAFAIU)が盗まれていない場合に潜在的に利益を得る可能性があることです。しかし、これは可能ですか?
つまり、キーを保護するには、sshの内部暗号化キーを使用して、サービスの起動時にそのキーをsshエージェントにロードすることもできます(サービスが停止したら削除することを忘れないでください!)。ただし、ssh-agentは鍵を暗号化されていない状態でメモリーに保持するため、鍵を読み取ることができることをもう一度覚えておいてください。つまり、はいこれ解決したい問題は何ですか?
2つのシステム間の通信のみを保護する必要がある場合、stunnel
SSHよりも優れたサービスを提供できます。
最後の質問は次のとおりです。SSHを開く(持ち運べる)、このオプションなど、他のプロセスからキーを読み取ることができる単純なパッチを作成することはssh
非常に簡単でなければなりません。sshd
AuthorizedKeysCommand
答え4
私はPythonを使用してキーペアを作成し、それをデータベースに保存するときにこの問題を解決しようとしています。以下は、ssh-agent
これを実行して対話するために使用したいくつかの手順です。 Pythonで書かれていますが、おそらく他の言語に翻訳することができます。もう1つの特徴は、それらを使用しないshell=True
ため、インジェクション攻撃からより安全であることです。
import subprocess
import os
sockfile = '/some/place.sock'
agent = subprocess.Popen(['ssh-agent',
'-D', # foreground mode
'-a', sockfile, # bind address (socket file)
])
subprocess.check_call(['ssh-add',
'-D', # delete all identities from the agent
],
env={'SSH_AUTH_SOCK': sockfile},
)
これはssh-agent
私たちのプログラムでのみ動作するプログラムを起動し、それを消去します(私のユーザーキーをここにロードしていると思いますがわかりませんSSH_AUTH_SOCK
)ssh-agent
。他のプログラムに。
次に、ssh-add
秘密鍵を提供します(ここでは文字列として保存されていますが、シリアル化する必要dr.private_key
があるため、ASCIIでエンコードします)。
adder = subprocess.Popen(['ssh-add',
'-', # read key from stdin
],
env={'SSH_AUTH_SOCK': sockfile},
stdin=subprocess.PIPE,
)
adder.communicate(dr.private_key.encode('ascii'))
retval = adder.wait()
assert retval == 0 # added successfully
これで、SSHを使用するいくつかのアプリケーション(Gitなど)を使用するたびに、同じSSHプロキシソケットを使用してそれを参照します。
gitp = subprocess.Popen(
['git', '-C', os.path.abspath('../some-repo') ,'fetch'],
env={'SSH_AUTH_SOCK': sockfile},
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
print(gitp.communicate()[0].decode('ascii'))
そしてそれは素晴らしい作品です。唯一の「一時ファイル」は使用されたソケットでありssh-agent
、所有者だけがアクセスできるように生成され、エージェント終了時に削除される。