web-dev-qa-db-ja.com

SSHクライアントは、SSHサーバーが秘密鍵(クライアントの "known_hosts"ファイルの公開鍵のペア)を確実に保持するようにするにはどうすればよいですか?

SSHクライアントは明らかに何らかの方法でSSHサーバーを認証します。サーバーのキーが変更されると、SSHクライアントソフトウェアはサーバーのキーが変更されることについて大きな警告を出し、これはMitM攻撃である可能性があるためです。

ただし、クライアントはチャレンジを使用してこの認証を行いますか?つまり、SSHクライアントはサーバーの公開鍵を使用してランダムに生成されたデータの一部を暗号化し、サーバーを認証するために、サーバーが秘密鍵を使用してこれを復号化し、復号化されたデータを送り返すことを期待しますか?

3
Utku

セキュアシェル(SSH)トランスポート層プロトコル(RFC 4253) は、サーバー認証の方法を説明します。セクション7によれば、暗黙的および明示的なサーバー認証があります。暗黙的な認証には、クライアント間の共有秘密が必要です。明示的な認証とは、 "鍵交換メッセージに、サーバーの信頼性の署名またはその他の証明が含まれることを意味します"。これは、サーバーが通常使用する種類のサーバー認証です。つまり、サーバーにキーペアがあり、公開キーがクライアントに知られていて、接続のターゲットが一致する秘密キーを知っていることを確認する必要があります。

Diffie-Hellman鍵交換に明示的な認証が含まれる方法については、セクション8で説明します。基本的に、サーバーはサーバーの秘密鍵を使用してクライアントからのデータに署名し、鍵の所有権を証明します。クライアントは既知の公開鍵を使用してこの署名を検証します。これらのクライアント提供データにはランダムデータが含まれているため、古い署名を再生することはできません。より深い詳細については RFC自体 を参照してください。

3
Steffen Ullrich

このトピックについてもDigitalOceanに不満を持っているので、私はこの答えを提案します。参照は、Diffie-Hellman鍵交換中に主張する RFC425 のセクション8です。

まず、クライアントは以下を送信します。

  byte      SSH_MSG_KEXDH_INIT
  mpint     e

その後、サーバーは次のように応答します。

  byte      SSH_MSG_KEXDH_REPLY
  string    server public Host key and certificates (K_S)
  mpint     f
  string    signature of H

基本的に、 Diffie-Hellman鍵交換/生成 の間、クライアントは秘密鍵 "x"から鍵 "e"を作成します。サーバーは、「y」の「f」と同じことを行います。 "x"と "f"(クライアント)または "y"と "e"(サーバー)では、暗号化秘密キー "K"が両側で計算されます(Diffie-Hellmanマジックを見てみましょう)。

それからトリックが来ます:)大きな計算が両側で行われます: "H"。これは、e、f、サーバーの名前「V_S」、クライアントの名前「V_C」、以前のメッセージの内容(client/serverからの「SSH_MSG_KEXINIT」=「I_C」/「I_S」)などの多くを含む長い文字列のハッシュです。 、公開サーバーキー「K_S」、そして最後に重要なことですが、秘密キーK:

H =ハッシュ(V_C || V_S || I_C || I_S || K_S || e || f || K)

Hはこの情報をすべて知っているため、クライアントに明示的に提供されません。したがって、Hも計算できます。むしろ、サーバーはサーバー秘密鍵で計算されたHの署名を提供します。その後、Hと公開鍵K_Sを独自に計算することにより、クライアントはこの署名をチェックしてサーバーを認証できます。

IMHOの主なポイントは、少なくともK(秘密)と署名を混在させることです。MitMがそのようなメッセージを偽装することはできません。

1
Jérém'

このチェックはSSHクライアントによる認証ではないと思います。あなたが言っているのは、SSHクライアントのサーバーホストキーのキャッシュのようです。これはサーバーを識別するのに役立ちますが、認証ではありません

SSHには2つの認証シナリオ(私が知っている)があり、どちらの場合も、サーバーではなくクライアントが認証されます。

1)(デフォルト)単純なパスワード認証。サーバーはクライアントにパスワードを要求します。その場合、クライアントによるチェックはありません。

2)SSH鍵の使用-これには、クライアントマシンで秘密鍵を生成し、対応する公開鍵をサーバーにインポートすることが含まれます。この場合、あなたが説明していることと似たようなことが起こりますが、クライアントは独自の秘密鍵を使用してサーバーのメッセージを暗号化しています。次に、サーバーはこの暗号化されたメッセージをクライアントの公開鍵と照合します。秘密鍵が安全に保たれている場合、単純なパスワードよりも安全で管理が容易であると見なされています。

Digital OceanによるSSH鍵認証プロセスの良い内訳です

1
Ter9

これはあなたの質問に関連する回答のようです: 公開サーバーのSSHフィンガープリントを確認しています

つまり、SSHサーバーには、SSHクライアントからの接続を確立するときに使用される公開鍵と秘密鍵があります。サーバーは、その公開鍵のコピーをクライアントに提供し、検証のためにユーザーに提示されます。次に、ユーザーはサーバーの管理者とそのキーを検証し、キーを受け入れる責任があります。

いったん受け入れられると、ユーザーはキーが変更された場合にのみそれを再び見ることになります。キーが変更された場合、それは管理者によって、またはMITMスタイルの攻撃を介してサーバー上で行われた再キーである可能性があります。どちらがどれかを確認するには、管理者にキーを再確認する必要があります。

Public-Key Cryptography が機能する方法であるため、「チャレンジ」はありません。

EDIT:SSHサーバーは、インストール中にssh-keygenアプリケーションを使用してホストキーを自動生成します。これにより、通常、RSA、DSA、ecdsa、ed25519キー、またはそれらのバリエーション(構成によって異なります)が作成されます。

サーバーに接続するクライアントはssh-keyscanを使用してサーバーのフィンガープリントを確認し、検証のためにユーザーに提示します。そのキーを受け入れると、それは~/.ssh/known_hostsファイルに書き込まれて記憶されます。 sshクライアントがそれをサーバーに接続するたびに、フィンガープリントを読み取り、known_hostsファイルでフィンガープリントをチェックして、フィンガープリントが変更されていないことを確認します。その場合、ユーザーであるユーザーに、キーが変更されて接続が停止したという警告が表示されます。再度接続するには、手動でキーを削除または変更する必要があります。

$ ssh-keyscan some.remote.server
some.remote.server ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA8BPNr+Q8cQfU95jfJKIfAH+z0+q03QDeFH1ndeTC3Zf0EDjZOg1OXs+Xiwjgrkq+vcNIA5DPaux3aStrcSa5o1AjgBNKN4rMyaLMW1c5LUnSic2oE7YTGvO1AHL55+Z4rCiEbDHeK2LXwhZifNvqkxf44pKrIe8kCvt89dkRsCria4n5EedGazKxO0mvbHM9JSpg03CiD4B+/afOrZqCJrf5dYcDCmeiBPSn9vjiZzAl2NYj05GVSqoe8KeFQV9n4c4LtWfzSDshvLlypuSfylzhL3euWG6JP8G6HnBohSiSQFk/Y0VFX/4wYshKjN3px0ugYUrucXXv8Sznv6n1Dw==

私のシステムでknown_hostsファイルを開くと、そこにこの正確なエントリが表示されます。

編集2:

コメントを読んで、あなたはこの指紋ビットに行き詰まっているようです。フィンガープリントは、公開鍵暗号の公開部分です。この概念を完全に理解するために前にリンクしたので、これについてもっと読んでください。公開鍵暗号では、秘密鍵と公開鍵が数学的に同時に作成されます。このキーペアは、プライベートキーで暗号化されたもの[〜#〜]のみ[〜#〜]をパブリックで復号化できるという特別な機能を備えていますキーおよび公開キーで暗号化されたもの[〜#〜]のみ[〜#〜]を秘密キーで復号化できます。これは非対称暗号であり、対称暗号ではありません(暗号化/復号化に1つのキーを使用)。

また、公開鍵暗号の使用を理解するには、署名の仕組みを理解する必要があります。プレーンテキストでメッセージを書いてあなたに送信した場合、私がそれを送信したことはわかりません。代わりにプレーンテキストメッセージを作成し、メッセージのハッシュを含み、秘密キーを使用して暗号化された暗号化されたblobを追加すると、公開キーを使用してblobを復号化できます。元のプレーンテキストメッセージはハッシュされ、暗号化されたblobに含まれているハッシュと比較されます。

これと同じ概念がSSHにも適用されています。サーバーで使用されている秘密鍵だけがクライアントの公開鍵を処理できるため、それらが同じマシンであることを数学的に証明できます。私のコメントで述べたように、完全に一致する2つの秘密鍵を生成することはほぼ不可能であり、重複したフィンガープリントを提供します。別のサーバーの秘密キーとまったく同じ秘密キーを生成できた場合、はい、他のサーバーと同じフィンガープリントを使用します-これは今日不可能だと考えてください。

0
Andrew

Steffen Ullrichが示唆したように、RFC4253の一部を読みました。以下は非常に不完全な説明ですが、私が理解しているのは:

  1. クライアントとサーバーは、鍵交換の結果としていくつかの共有秘密を取得します。
  2. サーバーは、秘密鍵を使用してこれらの共有秘密に署名し、それをクライアントに送信します。
  3. クライアントは、サーバーの公開鍵を使用してこれを復号化します。結果がRFC4253に記述されているものと一致する場合、サーバーは認証されます。

ちょっと、私は思った:「ちょっと、なぜ明示的な認証メカニズムが必要なのですか?クライアントはサーバーに送信したものを暗号化するためにサーバーの公開鍵を使用しているので、サーバーが偽物である場合、サーバーはできません。クライアントが送信したものを復号化します。サーバーはクライアントの発言を理解できないため、サーバーは意味のある応答を生成できません。したがって、サーバーは意味のない応答です。」

さて、上の段落は完全に間違っています。クライアントとサーバーは対称鍵暗号化を使用して、鍵交換後に通信するためです。したがって、サーバー(および場合によってはクライアント)の非対称鍵は、認証目的でのみ使用されます。コミュニケーションのためではありません。

0
Utku