web-dev-qa-db-ja.com

安全な方法でクライアント接続を認証するにはどうすればよいですか?

サーバーがポート1234でリッスンしているとしましょう。このポートに接続する必要があるクライアントソフトウェアがいくつかあります。しかし、悪意のあるユーザーがクライアントソフトウェアをバイパスして、他の方法(コンソールや別のソフトウェアなど)でポートに接続することを防ぎたいと思います。

信頼できるクライアントソフトウェアとサーバーは、必要に応じて秘密キーを共有する場合があります(キーをバイナリから抽出できる可能性があるので、私は生活できます)。このようなキーをプレーンテキストで送信したくないのですが、認証後のデータはプレーンテキストにすることができます。具体的には、悪意のあるユーザーが信頼されたクライアントソフトウェアを使用してサーバーチャレンジへの正しい応答を計算している中間者攻撃を阻止する方法を見つけようとしています。

ここからそこへ行けますか?

サーバーのリスニングポートをlocalhostにのみバインドし、クライアントが最初にssh経由でマシンにアクセスするように要求することもできます。次に、クライアントソフトウェアはsshライブラリを使用して、ローカルポートに接続するサーバー上でコマンドを実行します(このシナリオでは、悪意のあるユーザーはパスワードがないため、sshを使用してマシンにアクセスできません)。ただし、すべてのトラフィックは暗号化されます。これは追加のオーバーヘッドです。おそらく、認証だけを行い、その後チャネルをプレーンテキストのままにするsshに似たプログラムがあるでしょうか?

更新:

テストを実行して、すべてのトラフィックの暗号化に関連するオーバーヘッドを特定しました。

spew.rbは1000万行の100文字を出力します。

コントロール:

fantius@machine> time /home/fantius/spew.rb > /dev/null

real    0m35.015s
user    0m34.934s
sys     0m0.084s

上部は25%のCPU使用率を示しています(1つの完全なコア、4つのコア)

テスト:

fantius@machine> time ssh localhost /home/fantius/spew.rb > /dev/null

real    0m40.704s
user    0m19.981s
sys     0m1.400s

上の図は、45%のCPU使用率を示しています(ほぼ2つのフルコア)

そのメッセージ率はおそらくほとんどのマシン間接続を超えています。

6
Fantius

まず、暗号化のオーバーヘッドに関する想定を避けることをお勧めします。あなたは測定すべきです。 2001年の私のPCは、SSHを使用して100 Mbit/sリンクのフルスピードでデータを暗号化して転送するのに十分強力でした。実際のPC、2.4 GHzの一般的なCore2は、毎秒167Mバイト(はい、メガバイト、メガビットではない)でAES暗号化を実行できます。ギガビットイーサネットの場合、シングルコアを使用しています-他に3つのコアがあります。

クライアントを認証したい場合、クライアントには想定された悪意のあるユーザーにはない特別なものが必要です。暗号的に言えば、keyと呼ばれる秘密データの一部です。これは、そのキーが何であるかということです。アルゴリズムで使用される秘密データ秘密ではないと見なされます。これには、実際に回避できない構造上の欠陥が伴うことに注意してください。クライアントのコードへの読み取りアクセス権を持つ人は、リバースエンジニアリングを実行してキーを復元する可能性があります。これは、コードを難読化する手法によって少し難しくすることができますが、不可能にすることはできません。

また、接続を認証する必要があります。つまり、データトンネルを開始するだけでなく、実際に転送されるデータも認証します。それ以外の場合、認証ステップが実行されると、攻撃者は接続をハイジャックする可能性があります。これは [〜#〜] mac [〜#〜] と呼ばれる暗号の完全性チェックを使用することを意味します。その時点で、暗号化の追加は簡単です。 SSHは、対称暗号化とMACの両方を使用します。

既存の構成要素のうち、以下の解決策を提案します。

  1. SSHを使用します。クライアントはSSHを介して接続し、ハードコードされたパスワードを使用してそれ自体を認証します(パスワードは上記で説明したキーです)。中間者は、SSHの通常のメカニズムによって回避されます。つまり、SSHクライアントはサーバーの公開鍵のコピーを保持する必要があります。

  2. SSL/TLSを使用します。これは、SSHで発生することとよく似ています。サーバーの公開鍵はX.509証明書の一部として提示され、クライアントが署名して検証できるため、クライアントは正しいサーバーと通信していることをクライアントは知っています。クライアントは、証明機関の公開キーの知識が必要です。または、クライアントはすでにサーバー証明書を知っており、これがサーバーから送信された証明書と同じであることを確認するだけでもかまいません。トンネルが確立され、暗号化と整合性チェックが行われると、クライアントは自分のキーを「そのまま」送信し​​て、その身元を証明します。

  3. クライアント証明書でSSL/TLSを使用します。この設定では、クライアントに公開/秘密鍵のペアがあります。秘密鍵は私が話していた鍵です。公開鍵は、SSLハンドシェイク中にクライアントが表示する証明書にエンコードされます。これらはすべて標準のSSLであり、既存のSSLライブラリでサポートされています。ソリューション2と比較して、これにより、アプリケーションプロトコルにキー送信メッセージを含める必要がなくなり、MACのみの暗号スイートを使用できるようになります(暗号化の計算が高すぎることが判明した場合)(これは間違いです)。 。

  4. パスワード認証キー交換 でクライアントキーを使用して共通のセッションキーを取得し、MAC(および場合によっては暗号化)に使用します。 PAKEプロトコルのポイントは、低エントロピーの秘密、つまり人間のユーザーの頭に合うパスワードを許容できることです。 MACedトンネルの実行にはいくつかの微妙な点があるため、適切な方法は既存のプロトコルを使用することです。次に、これは TLS with SRP を要求します。 「パスワード」はクライアントでハードコーディングされています(SRPは短いパスワードを許容しますが、長くて非常にランダムなパスワードの使用を妨げるものはありません)。これは、証明書や既知の公開鍵による不正操作を抑制できるという点で優れています。クライアントは、パスワードの知識によって認証されます。同時に、サーバーはクライアントによってまたパスワード認証されます。さらにおまけとして、SRPでは、サーバーはクライアントから直接使用できないパスワードから派生したデータのみを保存するため、サーバーデータベースを読み取る攻撃者が「クライアント」として自動アクセスすることはありません。

私のお気に入りのソリューションはもちろんSRPを使用したものです。 elegantです。残念ながら、SRPはかなり新しいため、すべてのSSL/TLS実装がSRPをサポートしているわけではありません。しかし GnuTLS はそうです。

8
Thomas Pornin

すべてのことを言い終えたら、すべてが人間の介入なしで実行するように設計されている場合、サードパーティのクライアントがポートに接続するのを防ぐ実際の方法はありません。

この問題を防ぐ唯一の方法は、ハッキングできない(より正確には、ハッキングが難しい)システムで、識別情報、つまりユーザーを提供し、それらの資格情報が暗号化/ハッシュ方式で転送される場合です。資格情報として使用する予定の「秘密の」情報が何らかの方法でアプリケーション内に格納されている場合、悪意のあるユーザーがその情報にアクセスできます。

1
Steve