web-dev-qa-db-ja.com

署名されたJWTのリプレイ攻撃を防ぐことはできますか?

JWTを使用して、LaravelにHTTP経由のステートレス認証を実装しました。

  1. ユーザー名/パスワードをフロントエンドから送信します。
  2. サーバーはユーザーを認証し、有効期限付きの署名済みJWTを送り返します。
    • 私はHS512アルゴリズムを使用して秘密鍵で署名しています(サーバーでのみ使用可能)。
  3. フロントエンドは、将来のリクエストのためにトークンを保存します。
  4. フロントエンドは、トークンを含めて次のリクエストを送信します。
  5. サーバーは、トークンが有効で期限切れではないことを確認し、両方の場合にアクションを続行します。
  6. トークンが期限切れになると、サーバーは「ログアウト」メッセージを送信します。

これらの通信はすべてHTTPSを介して行われます。

したがって、これは次の点から安全であることがわかります。

  • HTTPSのため、攻撃者はトラフィックを傍受してJWTトークンを盗むことができません。
  • サーバーは秘密鍵を使用して署名を検証するため、攻撃者は奇妙なトークンを生成して送信することはできません。
  • トークン内のsubクレームの一部であるため、攻撃者はどのユーザー(つまり、リクエスターのロール+権限)がリクエストを行っているかを変更できません。

しかし、2つの質問があります

  1. ユーザーのコンピュータまたはモバイルにウイルスがあり、RAMまたはブラウザから有効なトークンを盗んだ場合、それはさらにリクエストを送信でき、それらは受け入れられます。これから守る方法はありますか?
  2. このシステムを攻撃する別の方法はありませんか?
30
Aditya M P

説明されているjtiクレーム here は、今後のリプレイ攻撃を防ぐためのオプションのメカニズムです。スペックから:

4.1.7。 "jti"(JWT ID)クレーム

「jti」(JWT ID)クレームは、JWTの一意の識別子を提供します。識別子の値は、同じ値が別のデータオブジェクトに誤って割り当てられる可能性が無視できる程度であることを保証する方法で割り当てる必要があります。アプリケーションが複数の発行者を使用する場合、異なる発行者によって生成された値間の衝突も防止する必要があります。 「jti」クレームは、JWTが再生されないようにするために使用できます。 「jti」値は、大文字と小文字が区別される文字列です。このクレームの使用はオプションです。

これは最終的にサーバーをステートフルにしますが、異常な動作を検出した場合、またはユーザーが不審なアクティビティを報告した場合、無制限の再生を防ぎます。次のシナリオを考えます。

  1. ユーザーがログインします。サーバーはJWTを生成し、署名といくつかのメタデータ(ユーザーIDと要求を行っているクライアントのタイプ、およびjti)を保存します。
  2. ユーザーが不審な行動を報告しています。
  3. アプリケーションは、ユーザーに接続されたバックエンドストア内のすべてのJWTを削除することにより、すべてのデバイスのユーザーを「サインアウト」します。これで、アプリケーションは「有効な署名があることはわかっていますが、作成していないため、受け入れません」と言うことができます。
    • メタデータが十分に正確であれば、jtiと追加情報を使用して、たとえば、特定のデバイスからのみユーザーをサインアウトさせることができます。

上記のように、これは必然的にサーバーをステートフルにします。これはまた、リプレイ攻撃を完全に防ぐわけではありませんが、攻撃が検出された後、そのような攻撃をさらにシャットダウンする可能性があります。

代替/追加の方法は、ユーザーに不便をかける可能性があるリスクを冒して、リプレイ攻撃をある程度完全に防ぐことができます。ログイン時にユーザーのIPアドレスをクレームおよび保存されたメタデータの一部にして、JWTを使用するIPが期待したものであることを確認します。これは、ユーザーが自宅とコーヒーショップの両方で機能していると言うユーザーにとっては苛立たしいことかもしれませんが、セキュリティの高いアプリケーションでは許容できる要件となる可能性があります。

23
bretmattingly

Webアプリケーションの同じコンテキストで実行されるコードがある場合、それがブラウザーでのXSS攻撃の一部であるか、ユーザーマシン上のマルウェア/ウイルスであるかに関係なく、それらの要求をユーザーの要求と区別することは困難(不可能?)自分の。

攻撃者がコンピューターにアクセスできる場合は、アプリケーションからサーバーへの通常の要求からデータを盗むこともできます。

潜在的に、いくつかのサーバー側侵入検知スタイル分析があります。リクエストまたはアイテム数が多いかどうかを確認します。 Webアプリケーションのどのコンポーネントがデータ要求を行うかがわかっている場合に、カスタムリファラースキームを適用します。次に、異常な動作を検出したときに再認証をトリガーしますか?また、JWTに埋め込まれたexpの上にJWTを期限切れにするサーバー側の方法も必要です。

4
Kevin Hakanson

ペイロードと有効期限として日時を持たないのはなぜですか?ペイロードを変更する必要はなく、アプリケーションロジックはトークンを期限切れにすることができます。または、リーフの性質に基づいて新しいシークレットを使用します( [〜#〜] dukpt [〜#〜] と同様)。これにより、新しいトークン要求が古いものを無効にします。

1
TheBB