JWTが盗まれた場合はどうなりますか?


201

RESTful APIのステートレス認証をJWTで実装しようとしています。

AFAIK、JWTは基本的に、REST呼び出し中にHTTPヘッダーとして渡される暗号化された文字列です。

しかし、リクエストを見てトークン盗む盗聴者がいる場合はどうでしょうか?それから彼は私のアイデンティティでリクエストを偽ることができますか?

実際、この問題はすべてのトークンベースの認証に当てはまります。

それを防ぐ方法は?HTTPSのような安全なチャネル?


1
これが、トークンが短期間のみ有効であることが多い理由です。データの機密性が心配な場合は、HTTPSを使用してください。
Jonathon Reinhart、2015

4
@JonathonReinhartしかし、トークンが間もなく期限切れになると、クライアントは時々自分自身を再認証して新しいトークンを取得する必要があります。面倒じゃないですか。
smwikipedia

@JonathonReinhartトークンが短命である理由を理解したと思います。そのため、サーバーはトークンの有効期限を追跡する必要がなく、スケーラビリティを確保する必要がありません。それは一種のだtrade-offとのhaving finer control of token expirationhaving better scalability
smwikipedia

2
これも役立ちますか?-「トークンの盗難を検出するための一般的なセキュリティメカニズムは、要求IPアドレスの発信元を追跡することです。」-ここの最後のセクションで詳細に説明-firebase.google.com/docs/auth/admin/manage-sessions
Ula

3
理論的には、トークンの盗難を防ぐことは不可能です。私たちにできる最善のことは、それが起こったことを検出して、できるだけ早くセッションを取り消すことです。検出に最適な方法は、ローテーション更新トークンを使用することです(RFC 6819で提案されています)。これを詳細に説明するブログは次のとおりです。supertokens.io
blog /

回答:


284

私は認証をかなり詳細に処理するノードライブラリであるexpress-stormpathの作成者なので、ここでいくつかの情報を紹介します。

まず、JWTは通常暗号化されません。暗号化JWTsへの道がありますが(参照:JWEsを)、これは多くの理由のために実際には非常に一般的ではありません。

次に、あらゆる認証形式(JWTを使用するかどうかにかかわらず)は、MitM攻撃(中間者)攻撃の対象になります。これらの攻撃は、攻撃者がインターネット経由でリクエストを送信するときにネットワークトラフィックを表示できる場合に発生します。これはあなたのISPが見ることができるもの、NSAなどです。

これは、SSLが防止するのに役立つものです。コンピューターからのネットワークトラフィックを暗号化することにより、>認証時に一部のサーバーが、ネットワークトラフィックを監視しているサードパーティは、何らかの方法でトークン、パスワード、またはそのようなものを見ることができない限り、それらを見ることができません。サーバーのプライベートSSLキーのコピーを取得する(可能性は低い)。これが、すべての認証形式でSSLが必須である理由です。

ただし、誰かがあなたのSSLを悪用してトークンを表示できるとしましょう。質問に対する答えは「はい」です。攻撃者そのトークンを使用してあなたになりすまし、サーバーにリクエストを送信することができます。

これがプロトコルの出番です。

JWTは認証トークンの1つの標準にすぎません。彼らはほとんど何にでも使用できます。JWTが優れている理由は、JWTに追加の情報を埋め込むことができ、誰もそれを悪用していないこと(署名)を検証できることです。

ただし、JWT自体は「セキュリティ」とは関係ありません。すべての意図と目的で、JWTはAPIキーとほぼ同じです。つまり、どこかのサーバーに対して認証するために使用するランダムな文字列だけです。

あなたの質問をより興味深いものにしているのは、使用されているプロトコルです(おそらくOAuth2)。

OAuth2が機能する方法は、クライアントに一時的なトークン(JWTなど)を与えて、短い期間のみの認証を行うように設計されているということです。

つまり、トークンが盗まれた場合、攻撃者はトークンを短期間しか使用できません。

OAuth2を使用する場合は、ユーザー名/パスワードまたはAPI資格情報を提供し、引き換えにトークンを取得することで、サーバーを頻繁に再認証する必要があります。

このプロセスは時々発生するため、トークンは頻繁に変更され、攻撃者が大きなトラブルを犯さずに常にあなたになりすますことが困難になります。

うまくいけば、これが役に立ちます^^


3
次の記事の著者は、JWTの欠点は、盗まれたJWTから回復する唯一の方法は、新しい鍵ペアを生成してすべてのユーザーを効果的にログアウトすることであると主張している。一方、セッションIDがDBに保存されている場合、Webサイトは影響を受けるユーザーのセッションのみを削除し、すべてのデバイスからログアウトできます。OAuth2がこの図にどのように適合するか、または提示された欠点を軽減するのに役立つかどうかはわかりません。medium.com/@rahulgolwalkar/…–
マルセル

4
著者が間違っています。トークンを無効にするために使用できるさまざまな設計パターンがあります。しかし一般的には、あらゆる種類の認証目的でJWTを使用することは悪い考えです。暗号で署名されたセッションのアイデアが埋め込まれたセッションCookieを使用する方がはるかに効率的です。
rdegges

1
@rdeggesは、JWTが認証にとってどのように悪い考えであるか教えてください。上記のコメントで言及したセッションCookieをどのように使用できますか?
noman tufail

6
これは、1つの応答を入力するには長すぎます。あなたがもっと学びたいなら、私はその主題について詳細な話をしました。私のスライドはオンラインでチェックできます。speakerdeck.com
rdegges

2
理論的には、トークンの盗難を防ぐことは不可能です。私たちにできる最善のことは、それが起こったことを検出して、できるだけ早くセッションを取り消すことです。検出に最適な方法は、ローテーション更新トークンを使用することです(RFC 6819で提案されています)。これを詳細に説明するブログは次のとおりです。supertokens.io
blog /

31

私はこれが古い質問であることを知っていますが、私はここに私の$ 0.50を落とすことができると思います、おそらく誰かが私のアプローチを完全に拒否するために改善または議論を提供することができます。HTTPS(ofc)上のRESTful APIでJWTを使用しています。

これが機能するためには、有効期間の短いトークンを常に発行する必要があります(ほとんどの場合に応じて、私のアプリでは実際にexpクレームを30分、ttl3日に設定しているため、トークンttlがまだある限り、このトークンを更新できます有効で、トークンはブラックリストに登録されていません)

についてはauthentication service、トークンを無効にするために、いくつかの基準に応じて、インメモリキャッシュレイヤー(私の場合はredis)をJWT blacklist/のban-list前に使用するのが好きです(RESTfulの哲学に反することはわかっていますが、保存されているドキュメントは私は彼らの残りの有効期間をブラックリストに載せているので、本当に短命です-主張- ttl

注:ブラックリストに登録されたトークンは自動的に更新できません

  • user.passwordまたはuser.email更新された場合(パスワードの確認が必要)、認証サービスは更新されたトークンを返し、以前のトークンを無効化(ブラックリスト)するため、クライアントがユーザーのIDが何らかの形で侵害されたことをクライアントが検出した場合、そのユーザーにパスワードの変更を依頼できます。ブラックリストを使用したくない場合は、iat(発行された)クレームをuser.updated_atフィールドに対して検証できます(jwt.iat < user.updated_atJWTが有効でない場合)。
  • ユーザーが故意にログアウトしました。

最後に、誰もが行うように通常どおりにトークンを検証します。

注2:トークン自体(本当に長い)をキャッシュのキーとして使用する代わりに、jtiクレーム用にUUIDトークンを生成して使用することをお勧めします。これは良いことだと思います(ちょうど頭に浮かんだので定かではありません)、これと同じUUIDをCSRFトークンとして使用することもできます。それには、secure/ non-http-onlycookieを返し、X-XSRF-TOKENjsを使用してヘッダーを適切に実装します。このようにして、CSRFチェック用のさらに別のトークンを作成する計算作業を回避できます。


9
アイデアを投稿するのに遅すぎることはありません。お返事をありがとうございます。
smwikipedia 2018

2
リクエストごとにチェックする必要があるブラックリストをサーバーに保存する場合、単純な古いセッションを使用しないのはなぜですか?
フランクリンユー

@FranklinYuブラックリストは、完全なセッションストアよりも「安価」です。存続期間の短いKey-Valueオブジェクトを保存しているため(残りの存続期間によって異なりますが、かなり短いはずです)、これはサインアウトアクションとトークンを無効にするようなアクションでのみ発生するため、すべてのトークンが格納されたofc。
Frondor 2018年

2
それはどれくらい安いのですか?まず、サーバー側に何かを保存している場合、すべてのアプリケーションサーバーが何かを実行する前に通信する必要がある中央ブラックリストサーバーがまだあるため、JWTが主張する「スケーラビリティ」のメリットを享受できません。有効期限が短いために1kブラックリストのみを保存する必要がある場合は、セッションに対して同じことを実行できるため、1kセッションのみを保存する必要があります。
フランクリンユー

3
私はこのアプローチが好きです。実際には、各リクエストのブラックリストをチェックする必要はありません。JWTの有効期限が切れた後(トークン自体から読み取ることができます)、およびその後のTTL期間までに発生するリクエストについてのみチェックしてください。「標準」の使用例では、特定のトークンの存続期間中に1回だけ発生します。更新後は、今後の更新リクエストを拒否することができます。ありがとう@Frondor
John Ackerman

7

これについて少し遅れて申し訳ありませんが、同様の懸念があり、今はそれに何かを貢献したいと思っています。

1)rdeggesは、JWTが「セキュリティ」とは何の関係もなく、ペイロードをめちゃくちゃにしたかどうかにかかわらず、単に検証するという優れた点を追加しました(署名)。sslは違反の防止に役立ちます。

2)さて、sslも何らかの形で侵害された場合、盗聴者は無記名トークン(JWT)を盗んで本物のユーザーになりすますことができます。次のレベルのステップは、クライアントからJWTの「所持証明」を探すことです。 。

3)これで、このアプローチでは、JWTのプレゼンターは特定のProof-Of-Possession(POP)キーを所有します。これにより、受信者はリクエストが同じ認証済みユーザーからのものかどうかを暗号で確認できます。

私はこれについてPoofsionの記事を参照し、そのアプローチに確信を持っています。

何か貢献できれば嬉しいです。

乾杯(y)


0

クレームの一部として、このJWTトークンの生成を要求した最初のホストのIPを追加することはできませんか?これで、JWTが盗まれて別のマシンから使用されたときに、サーバーがこのトークンを検証するときに、要求されたマシンのIPがクレームの一部として設定されたマシンのIPと一致するかどうかを確認できます。これは一致しないため、トークンを拒否できます。また、ユーザーが自分のIPをトークンに設定してトークンを操作しようとすると、トークンが変更されるため、トークンは拒否されます。


これは考えられる解決策の1つですが、ファイアウォールの背後にあるクライアントでは、IPアドレスがアドレスのプールから選択されるのが一般的であり、いつでも変更できます。
SpeedOfSpin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.