ユーザー認証の不備が JSON Web トークンに与える脅威の分析
エグゼクティブサマリー
Akamai のリサーチャーは、Open Web Application Security Project(OWASP)の 「API セキュリティトップ 10」に含まれている、ユーザー認証の不備の攻撃ベクトルとしての JSON Web トークン(JWT)を分析し、JWT の脅威と傾向が現れるさまざまなシナリオを明らかにしました。
JWT は、ユーザーを安全に検証するためのトークン(通常はクライアントとサーバー間)を発行することにより、API のセキュリティを確保する役割を担っています。こうしたトークンは、一般的な検証形式の 1 つとして広く使用されており、JSON オブジェクトの形式で共有される情報を含んでいます。
各トークンは暗号化されていませんが、エンコードされており、検証の署名が付与されています。Akamai は、不正な実装や、低エントロピーで短いシークレットキーが原因で大量に発生した JWT への脅威の一部を調査しました。
JWT ユーザーと組織が API のトークンとして JWT を選択する際に直面している大きな潜在リスクは、アカウントの乗っ取り、権限の昇格、データの漏えいの 3 つです。対称アルゴリズムは理論的に安全性が低いにもかかわらず、Akamai のトラフィックでは、ほとんどの JWT がこのアルゴリズムを使用していることがわかりました。
この投稿では、これらの JWT の脅威に対応するためのベストプラクティスを紹介します。
概要
JWT は、多くのリスクを排除し、比較的簡単に実行できるトークンスキーマとして広く使用されています。JWT の実装とセキュリティ確保の際は、こうしたリスクを考慮する必要があります。JWT に対する最も顕著なリスクの 1 つは、 OWASP API Security Top 10にも挙げられている、ユーザー認証の不備です。
ユーザー認証の不備は、リクエストしているユーザーの認証情報と ID が API によって適切に検証されていない場合に発生します。残念ながら、この脆弱性は JWT に多く観測されており、攻撃者が別のユーザーのアカウントになりすましたりアクセスしたりして、権限の昇格やデータの漏えいを引き起こす恐れがあります。
パイプラインの保護
JWT は、API および Web アプリケーションで一般的に使用される認証トークンです。Akamai のトラフィックでは、Web アプリケーションによってより多くの API が使用され、顧客に公開されており、さまざまな API エンドポイントにおけるシームレスな認証の必要性が高まっていることがわかりました。
API は組織の主要なパイプラインとして、認証および承認メカニズムの保持、データベースの照会、組織の多くの機能の公開という役割を担っています。そのため、API フィールドでは JWT の脅威の危険性が高まっています。このブログの投稿では、JWT の基本知識、JWT に対する 6 つの脅威、これらの脅威への対処方法について説明します。
JWT の基本知識
JWT は、Web アプリケーション、モバイルアプリケーション、および API でデータを送信するための署名付き JSON データを送信するための形式であり、主に認証のみに使用されます。JWT 構造は、ヘッダー(Jose ヘッダーとも呼ばれます)、ペイロード、署名の 3 つの要素で構成され、すべてドットで区切られています(図1)。
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIiLCJpYXQiOjE2NzYyMTc5NTAsImV4cCI6MTcwNzc1Mzk1MCwiYXVkIjoiYWthbWFpLWJsb2ciLCJzdWIiOiIiLCJjb21wYW55IjoiQWthbWFpIiwidXNlciI6IkFrYW1haS1yZWFkZXIiLCJhZG1pbiI6Im5vIn0.kMPz3Z7BSlBTJKijD8bcrpzTZejX7VCZ77w5oQwJO6I
図 1:JWT 構造を成す 3 つの要素の例
ヘッダーとペイロード
ヘッダーとペイロードは、両方とも Base64、URL セーフにエンコードされ、 IETF 指定の 推奨フィールドになっています(図 2)。「エンコード」とは、人間には直接読み取ることはできないがサーバーは簡単にデコードできることを意味します。その目的は、「URL セーフ」を維持しながら、データの整合性と使いやすさを確保することです。このようにして、Web ブラウザーで使用される文字の重複を回避しています。
JOSE ヘッダーは、JWT と JSON Web Encryption(JWE)の両方に使用されます。JWE は、大まかに言うと、暗号化されている JWT で、一般的な JWT 攻撃の大半を回避する際に効果を発揮します。選択したトークンメソッドを指定するフィールドは、「typ」(typ:JWT/JWE)です。ペイロードには、実装に応じて登録されたフィールド(Internet Assigned Numbers Authority によって主張)またはカスタムフィールドが含まれます。
図 2:エンコードされた JWT
署名
署名の目的は、トークンの検証です。つまり、トークン生成以降、サーバーによるトークンの偽造とデータの変更がないことを検証します。
署名を作成するには、主に次の2つの手順を実行します。
暗号化アルゴリズム(MAC など)を、ドットで区切られたヘッダーとペイロードに適用する(アルゴリズムは秘密鍵を使用する)
ハッシュアルゴリズム(SHA256など)を暗号化されたヘッダーとペイロードに適用する
JWT の使用時に、サーバーではトークン自体を検証するために署名が検証されます(今回の投稿では、後半で検証用のさまざまなアルゴリズムについて説明します)。
JWT は、(大規模な場合も含めて)使いやすく、実装が容易で、サーバーの必要なデータがクライアント側で保存されるため、Web アプリケーションでの認証に広く使用されています。ただし、JWT は署名されていても、リスクが伴います。JWT はプレーンテキストを使用しており、各実装は異なるペイロードフィールドで構成されています。そのため、アタックサーフェスが広く、エラーの余地も十分にあります。
JWT が直面している一般的かつ興味深い脅威を調査することで、脆弱性に対する意識の向上、悪意のあるふるまいの容易な検知、リスクの適切な緩和、必要なセキュリティ対策による潜在的な脆弱性からの保護を実現できます。
Akamai は、ユーザーがより安全なアプローチによって JWT を使用して作業し、セキュリティ専門家や管理者にデューデリジェンスを実施するために必要なツールと推奨事項を提供することを目標としています。
JWT に対する 6 つの脅威
1.検証なしでサーバーがトークンを使用できるようになる
JWT は暗号化の代わりに署名を使用するため、事前に検証を行う必要があります。アプリケーションによる検証がまったく行われない最も基本的な脅威シナリオの場合、攻撃者はペイロードを編集(例: 権限の昇格)して署名に触れずにおくことができます。あるいは、削除してより高い権限を取得することもあります。
もう 1 つ考えられるのは、トークンの署名に使用されたアルゴリズムを表すヘッダーの「alg」パラメータを使用する方法です。「None」は正当な値であるため(JWT は Unsecured JWT という名前になります)、誰でも容易にトークンに署名できます。バックエンドでは、JWT 検証の実装も可能です。
このアプローチは、まずヘッダーの「alg」フィールドの探索から始めます。その後、指定されたアルゴリズムを使用してトークンを検証します。「None」アルゴリズムでは、そのトークンの署名と検証は必要ありません。トークンのペイロード、ヘッダーを(alg:none)に編集し、「自己署名」(署名を削除)すれば、攻撃の成功です。
Example
図 3 に、デコードされた JWT の例を示します。
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiZXhhbXBsZSBuYW1lIiwiaWF0Ij
oxNjU5MjM5MDIyfQ.PrhAp2DUWXoL01_odyLATuzrwn5rMtY1IVsP8y4LH5E
decoded:
{
"alg": "HS256",
"typ": "JWT"
}
.{
"name": "example name",
"iat": 1659239022
}
図 3:デコードされた JWT の例
API エンドポイントでは、検証のために選択したアルゴリズムとしてペイロードの「alg」フィールドを使用するものと仮定します。
しかし、ここでは JWT を編集します(図4)。このようにして、別のユーザーの有効な JWT の偽造に成功しました。
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJuYW1lIjoiZXhhbXBsZSBuYW1lIiwiaWF0Ijo
xNjU5MjM5MDIyfQ.
decoded:
{
"alg": "none",
"typ": "JWT"
}
.{
"name": "other person's name",
"iat": 1659239022
}
図 4:alg:none を不正利用するために編集した JWT
ベストプラクティス: これは簡単です。 必ず トークンを使用する前に、ハードコーディングされた事前定義アルゴリズムを使用して検証します。alg パラメータを検証アルゴリズムのポインタとして使用しないでください。
2.異なるアプリケーションに同じ秘密鍵を使用する
アプリケーションごとに別の登録をするようにしている企業は多数あります。同じ秘密鍵を使用すると、異なるユーザー ID の 2 つのアプリケーションで有効なトークンが作成されます。その場合は、1 つ目のアプリケーショントークンで 2 つ目のアプリケーションにリクエストを行い、 アカウントを引き継ぐことになります (選択の余地はありません)(図5)。
ベストプラクティス: 簡単な経験則が効果的です。ユーザー ID を切り離す際、別の秘密鍵を使用してください。
3.弱い署名アルゴリズムを使用している
アルゴリズムには、主に対称(HSXXX)と非対称(RSXXX、ESXXX、PSXXX)という 2 種類のファミリーがあります。対称アルゴリズムでは、共有の秘密鍵が 1 つ必要です。非対称アルゴリズムでは、秘密鍵と公開鍵が必要です(表 1)。
対称 |
|||
---|---|---|---|
HSXXX |
HMAC + SHA |
安全性が比較的低いアルゴリズム |
共有の秘密鍵を使用 |
非対称 |
|||
RSXXX |
RSA + SHA |
より安全なアルゴリズム |
秘密鍵と公開鍵を使用 |
ESXXX |
ECDSA + SHA |
3 種類のアルゴリズムの中で最も安全性が高い |
秘密鍵と公開鍵を使用 |
表 1:アルゴリズムの 2 つの主要なファミリー
攻撃者の視点からは、対称アルゴリズムの方が総当たりが容易で、公開鍵を収集する必要はなく、考えられる限り最高の効率で計算可能です。Akamai のトラフィックでは、非対称アルゴリズムよりも対称アルゴリズムの方が広く使用されています(図 6)。
理論的に考えると、対称アルゴリズムは計算が少なくて済むため、大規模なケースでは非対称アルゴリズムよりもパフォーマンスが上回る場合があります。
ベストプラクティス: 非対称アルゴリズムを使用する。現在最も安全な方法(暗号化)である ECDSA アルゴリズムを使用することをお勧めします。秘密鍵が高いエントロピーで十分な長さを持っている場合は、適切にセキュリティを確保している対称キーを使用しても構いません。
4.短く、低エントロピーの秘密鍵を使用している
短く、低エントロピーの秘密鍵は、迅速かつ低コストな総当たり攻撃の標的になる可能性があります。世の中には、グラフィックス・プロセシング・ユニット(GPU)を搭載した高性能クラウド環境にインストール可能な使いやすいクラッキングソフトウェアが存在します。GPU の性能は急速に向上しており、クラッキング能力にもその影響が及んでいます。今日のハイエンド・グラフィックス・カードは、3 年前に比べて約 2.5 倍のスピードでクラック可能です。
8 文字の秘密鍵のクラックに必要な日数(エントロピーは無関係とする)を 3 年前と現在で比較した結果を表 2 に示します。
ハイエンド・グラフィックス・カード |
クラックに要した日数 |
---|---|
3 年前 |
10.5 日 |
今日 |
4.5 日 |
表 2:8 文字の秘密鍵を解読するのにかかる日数
数年前、7 文字の秘密鍵を解読するのに約 24 時間かかっていました。今では90 分未満でそれが可能です。この攻撃のユニークな点は、オフラインで実行するところです。組織側からは防御するどころか、そのような攻撃を受けていることすら知る方法もありません。
ご自身が国の支援を受けた攻撃者として、そのような攻撃のためにオーケストレーションされたシステムを構築している様子を想像してみてください。JWT の秘密鍵を保持すれば、攻撃者は署名付きトークンを偽造し、その ID を知っているだけで他のユーザーになりすますことができるのです。
ベストプラクティス: 10 文字以上の長い、高エントロピーの秘密鍵を使用する。秘密鍵の生成に RSA を使用することをお勧めします。
5.機密データを JWT のペイロードに保存している
JWT は Base64 URL エンコードされているため、ペイロードは暗号化されません。DB 名、増分 ID(すべての種類)、またはサーバーの内部フィールドとデータを格納すると、過度のデータ漏洩が発生し、他の攻撃ベクトル(たとえば、オブジェクトレベルの権限の破損など)における攻撃を助長する恐れがあります。
ベストプラクティス: 機微な情報を JWT に保存しない。機微な情報を保存する必要がある場合は、JWE を使用してください。
6.鍵の悪用
非対称アルゴリズムでは、JWT(署名部分)を作成するために秘密鍵が使用され、JWT を検証するために公開鍵が使用されます。攻撃者は、ヘッダーで指定されたアルゴリズムを対称的なアルゴリズム(HS256など)に変更し、サーバーによる検証に使用されている正当な公開鍵を悪用して署名を作成します。
その場合、適切に実装されていないバックエンドは公開鍵を使用して(ヘッダーで指定された攻撃者として)対称アルゴリズムを実行し、攻撃者によって偽造された JWT の検証に成功するのです。
Example
図 7 は、新しい JWT を偽造するサーバーのプロセスを示しています。図 8 は、サーバーの JWT 検証プロセスを示しています。
検証の最後の部分における比較のスローエラーは、次の 2 つの理由のいずれか(または両方)が考えられます。
ヘッダーとペイロードは編集されたが、署名は編集されなかった
アルゴリズムまたは鍵は正しいが設定ミスがある
図 9 は、鍵を悪用した主な攻撃を示しています。
最終ステップ:サーバーは、図 8 に示すプロセスでトークンを検証します。このプロセスでは、サーバーは alg フィールドを信頼します。公開鍵を秘密鍵として HS256アルゴリズムを実行してトークンを検証します。まさに攻撃者の思いどおりです。
ベストプラクティス: 検証プロセスで事前定義されたアルゴリズムを使用し、ユーザー入力を信頼しない。
結論
JWT は最も広く使われている認証トークンです。何度もサインインする必要がなく、認証中に多くの Web アプリケーションや API を使用できます。その一方で、JWT は暗号化されておらず、セキュリティを考慮して実装されていないため、多くの脅威が存在します。
コンピューターの能力は急速に進化しているため、脆弱な秘密鍵はリスクがあり、数年どころか数日でクラックされる可能性があります。JWT の場合、この種の攻撃は、組織が攻撃を認識していなくてもオフラインで実行される可能性があります。
対称アルゴリズムは最も広く使われており、それだけに攻撃者にとって作業が容易になります。
認証攻撃のような複雑な脅威も存在しますが、攻撃者が認証攻撃を自動化するのは困難です。しかし、JWT 攻撃ベクトルは単純で、自動化され、大規模に悪用される恐れがあります。
こうした理由(およびその他の多くの理由)から、ユーザーは JWT の脆弱性とセキュリティのベストプラクティスを把握した上で潜在的な脆弱性から保護することが重要です。OWASP API セキュリティのトップ 10 の脅威として挙げられている「ユーザー認証の不備」から JWT を保護する有用なガイドとして、この分析結果がお役に立てれば幸いです。