web-dev-qa-db-ja.com

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

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

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

しかし、リクエストとトークンを盗むを見る盗聴者がいる場合はどうでしょうか?その後、彼は私の身元でリクエストを偽造することができますか?

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

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

148
smwikipedia

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

まず、JWTは通常ではなく暗号化されます。 JWTを暗号化する方法はありますが( JWEs を参照)、これは多くの理由で実際にはあまり一般的ではありません。

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

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

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

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

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

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

あなたの質問をより興味深いものにしているのは、使用されているプロトコル(ほとんどの場合OAuth2)です。

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

アイデアは、トークンが盗まれた場合、攻撃者は短期間しか使用できないというものです。

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

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

これがお役に立てば幸いです^^

227
rdegges

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

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

authentication serviceの場合、トークンを無効にするために、メモリ内キャッシュレイヤー(私の場合はredis)をJWT blacklist/ban-listとして使用したいフロント、いくつかの基準に依存します:(RESTful哲学を破ることは知っていますが、保存されたドキュメントは本当に短命です。残りの存続時間-ttlクレームをブラックリストに載せています)

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

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

最後に、すべての人が行うように、トークンを正常に検証します。

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

22
Frondor

これに少し遅れて申し訳ありませんが、同様の懸念があり、同じものに貢献したいと思っています。

1) rdegges 優れた点を追加しました。JWTが「セキュリティ」とは何の関係もなく、ペイロードを台無しにした(署名)場合、単に検証するだけです。 sslは、侵害の防止に役立ちます。

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

3)現在、このアプローチでは、JWTのプレゼンターは特定のProof-Of-Possession(POP)キーを所有しています。受信者はこれを cryptographically 要求が同じ認証ユーザーからのものかどうかを確認できます。

Proof of Possesion の記事を参照し、このアプローチに納得しています。

何か貢献できたら嬉しいです。

乾杯(y)

2
yanky_cranky