REST APIを開発していますが、自己署名証明書を使用しないとHTTPSを使用できません。これは、いくつか、しかし私はクライアントブラウザにポップアップするセキュリティメッセージが欲しくない。
ネットワーク上で渡される情報は機密ではないため、盗聴は気にしませんが、許可されたクライアントのみが要求を実行して、リプレイ攻撃を防ぐことができるようにしたいと思います。これが私の考えです:
ユーザーは、サービスを実行するWebアプリケーションに登録されます。 APIクライアントを登録したいが、開発者ではないため、提供されたクライアントアプリケーション(この例では、スキャンしたカードから読み取ったデータをWebサービスに通信できるコンピューターで使用するICカードリーダー)をダウンロードします。 APIを介して)。
ステップ1:APIクライアントアプリケーションはキーペア(OpenSSLなど)を生成し、公開キーをサーバーに送信します(これは、ユーザーがクライアントをサーバーに登録するときに手動でアップロードするステップです)。サーバーは、ユーザーに関連付けられたデータベースとクライアントの説明(「PC01上のICカードリーダー」など)に公開鍵を格納します。
キーペア(SSHなど)を使用したいのはなぜですか?共有シークレットは少なくとも1回はネットワーク経由で転送する必要があるため、盗聴に対して脆弱であると感じています。これは、ネットワーク経由で転送するのではなく、サーバーのターミナルに手動でキーを入力することで防止できますが、システムの設計目標の1つは、自分以外のユーザーがクライアントを登録し、Webインターフェイスを使用してAPIアクセストークンを取得できるようにすることです。応用。この状況では、盗聴者が共有秘密鍵を傍受する可能性がありますが、クライアントによって生成された鍵ペアはそれを阻止します。
ステップ2:要求を行うと、クライアントは最初にサーバーからナンスを取得し(ナンスのリストまたはデータベースに発行され、タイムスタンプが発行されます)、次に、要求に署名しながらナンスを含む要求を行います。秘密鍵を使用します。サーバーは、要求を実行する前に、メッセージが本物であること(クライアントによって署名され、他の誰も署名していないこと)を確認します。
このアプローチの私の目標は、有効なクライアントのみがAPIにアクセスできるようにすると同時に、リプレイ攻撃を防ぐことです。攻撃者はメッセージの内容を見ることができるはずですが(実際には機密ではありません)、メッセージを変更することはできません。クライアントは、サーバーからのデータが本物であるかどうかを本当に気にしません(この場合、クライアントはサーバーの状態を変更しているので、その逆ではありません)。
HTTPS(クライアント認証なし)は、実際には次の目標を達成するのに役立ちません。
このアプローチの私の目標は、有効なクライアントのみがAPIにアクセスできるようにすると同時に、リプレイ攻撃を防ぐことです。
HTTPS(クライアント認証なし)は、クライアントがサーバーになりすましている誰かと話すことを防ぎます。クライアントになりすましているユーザーが実際のサーバーと通信するのを防ぐことはできません。
したがって、適切なTLS証明書を取得できたとしても、所定の目標を達成するためにいくつかのセキュリティ対策を講じる必要があります。
このアプローチはこれらの設計目標を満たしていますか?
私はそれがそうだと言うでしょう、ただし以下を条件とします:
非対称署名(提案どおり)または対称署名(HMACなど)を使用できます。安全なチャネルで最初の交換(公開鍵または共有秘密のアップロード)が行われることを保証できれば、どちらのアプローチも機能するはずです。 Amazon HMACを推奨 および このライブラリ は、RSA、DSA、およびHMACをサポートしています。
また、中間者攻撃を防ぎますか(クライアントの元の登録が、攻撃者の偽のサーバーではなく、実サーバーで行われたと想定)。
場合によります。攻撃者は引き続きサーバーを偽装し、悪意のあるデータをクライアントに送ることができます(クライアントはサーバーを認証しないため、HTTPが役立つ可能性があります)。
同時に、認証データ(RSAの場合は公開鍵、HMACの場合は共有シークレット)の最初の交換が安全なチャネルを介して行われたことを確認できれば、サーバーは改ざんされた応答を検出して拒否できるはずです(つまり、 nonceまたは署名が無効なもの)、これはMITMに耐性のあるクライアント認証を提供します。
クライアントはサーバーを認証する手段を持たないため、この部分はプロトコルフロー(リクエストの開始者、データフローなど)に関して非常に注意深く評価する必要があります。
このアプローチの私の目標は、有効なクライアントのみがAPIにアクセスできるようにすると同時に、リプレイ攻撃を防ぐことです。
攻撃者はメッセージの内容を見ることができるはずですが(実際には機密ではありません)、メッセージを変更することはできません。
APIキーとシークレットを用意します。
リクエストには、平文のキーが含まれています。
また、「ハッシュ」値も含まれます。このハッシュ値は、APIシークレット、増え続けるナンス値、およびリクエスト自体のデータを連結したハッシュ(sha256など)です。サーバーは独自のハッシュを生成し、クライアントが送信したハッシュと比較します。
攻撃者はAPIリクエストを読み取ることができますが、APIシークレットを持っていないため、新しい「ハッシュ」値を作成して独自の任意のデータを送信することはできません。 nonceの値のため、彼は古いAPI呼び出しを再生することもできません。
いいえ、それはMITM攻撃を防ぐことはできません。サーバーの認証なしにクライアントを認証することはできません。クライアントがサーバーと通信していることが保証されているのに、サーバーが実際にクライアントと通信しているとは保証されていないのはなぜですか。
サーバーを認証せずに、これ:
クライアント<-------->サーバー
これと同じです:
クライアント<-----> MITM <-------->サーバー
MITMは、サーバーからクライアントへ、またはクライアントからサーバーへ送信されたものを変更できます。クライアントはMITMが見たいものだけを見て、サーバーにそれを作る唯一の要求はMITMによって許可されたものです。
したがって、例のクライアントではnonceを要求し、サーバーはnonceを送信します(MITMがコピーを作成します)。クライアントがリクエストを作成し、MITMがそれをインターセプトし、必要なものに変更してサーバーに中継します。サーバーはリクエストが本物であると信じています。
帯域外通信を使用してクライアントにID(フィンガープリント、または公開鍵)を提供する方法がある場合は、自己署名証明書を使用できました。このように、クライアントは、サーバーのhello(SSLハンドシェイクの一部)が予期されるサーバー証明書の事前共有「Id」と一致することを保証することにより、サーバーとの暗号化および認証通信チャネルを安全に確立できます。
これはあなたのシナリオでうまくいくかもしれませんが、ほとんどのシナリオでそれは鶏と卵の状況につながります。クライアントにサーバー証明書の有効なIDを安全に取得できれば、通信は安全ですが、そのためには、何らかの安全な通信が必要です。 CAのポイントは、bootstrapそのプロセスです。
OPがポートアクセスを443ではなく80に許可する理由はわかりません。その場合、HTTPS互換のポート(TCP/IPはすべて..)にインバウンドルールを設定できます。構成済みのポートについて設定し、HTTPSをセットアップするだけです。
また、APIについては、OWASPにAPIセキュリティのセット全体が表示されます。以下は、あなたが防御できるチートシートです。
https://www.owasp.org/index.php/REST_Security_Cheat_Sheet
これを実装することで、既成の優れたセキュリティ対策を実装することもできます。
https://www.owasp.org/index.php/ESAPI_Secure_Coding_Guideline
すべてのガイドは、OWASPコミュニティによって管理されています。 TLS証明書でセットアップに問題があるかどうかが不明です。問題がある場合は、このサポートについてベンダーにお問い合わせください。