Hacking JSON Web Tokens (JWTs) から学ぶ

ソース(member only):

medium.com

脆弱性:JWT

 

訳:

JSON Web トークンは、商用アプリケーションで広く使用されているアクセス トークンの一種で。
これらは JSON 形式に基づいており、トークンの整合性を保証するためのトークン署名が含まれていて。

今日は、JSON Web トークン (および署名ベースのトークン全般) を使用することによるセキュリティへの影響と、それらが攻撃者によってアクセス制御をバイパスするためにどのように悪用される可能性があるかについて説明し。

 

JSON Web トークンはどのように機能しますか?

JSON Web トークンは、ヘッダー、ペイロード、署名の 3 つのコンポーネントで構成され。

 

ヘッダー

JSON Web トークンのヘッダー セクションは、署名の生成に使用されるアルゴリズムを識別します。 これは、次のような JSON BLOB の Base64URL エンコード文字列です。

 

{
"alg" : "HS256",
"typ" : "JWT"
}
base64url encoded string:  eyBhbGcgOiBIUzI1NiwgdHlwIDogSldUIH0K

 

(Base64url エンコードは、URL 形式用の Base64 の修正バージョンで。Base64 に似ていますが、異なる非英数字文字を使用し、パディングを省略しています。)

 

使用される最も一般的なアルゴリズムは次のとおりです。 HMAC および RSA アルゴリズム 

 

ペイロード

ペイロード セクションには、アクセス制御に実際に使用される情報が含まれ。 このセクションも、トークンで使用される前に Base64URL でエンコードされ。

 

{
"user_name" : "admin",
}

base64url encoded string: eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg

署名

署名は、トークンが改ざんされていないことを検証するために使用される部分で。
これは、ヘッダーとペイロードを連結し、ヘッダーで指定されたアルゴリズムで署名することによって計算され。

 

signature = HMAC-SHA256(base64urlEncode(header) + '.' + base64urlEncode(payload), secret_key)

// Let's just say the value of secret_key is "key".

-> signature function returns 4Hb/6ibbViPOzq9SJflsNGPWSk6B8F6EqVrkNjpXh7M

 

この特定のトークンの場合、文字列 「eyBhbGcgOiBIUzI1NiwgdHlwIDogSldUIH0K.eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg」は、 秘密鍵 「key」 を使用して HS256 アルゴリズムで署名されます。 結果の文字列は 4Hb/6ibbViPOzq9SJflsNGPWSk6B8F6EqVrkNjpXh7M になります。 

 

完全なトーク

各セクション (ヘッダー、ペイロード、署名) を「.」で連結することで完全なトークンを取得します。 各セクションの間にあります。

eyBhbGcgOiBIUzI1NiwgdHlwIDogSldUIH0K.eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg.4Hb/6ibbViPOzq9SJflsNGPWSk6B8F6EqVrkNjpXh7M

 

JSON Web Token コントロールをバイパスする方法

JSON Web トークンを正しく実装すると、ペイロード セクションに含まれるデータは改ざんできないため、ユーザーを識別するための安全な方法が提供されます。 (ユーザーは秘密キーにアクセスできないため、自分でトークンに署名できません。)

しかし、実装が間違っている場合、攻撃者がセキュリティ メカニズムをバイパスし、任意のトークンを偽造する可能性があり。

 

アルゴリズムの種類を変更する

攻撃者が独自のトークンを偽造できる方法の 1 つは、 alg ヘッダーの フィールドを改ざんすることで。
アプリケーションが JWT で使用されるアルゴリズムの種類を制限しない場合、攻撃者が使用するアルゴリズムを指定でき、トークンのセキュリティが侵害される可能性があり。

 

1. None algorithm

 

JWT は 「none」 アルゴリズムをサポートします。 フィールドが「none」に設定されている場合 alg 、署名セクションが空に設定されていれば、トークンは有効であるとみなされ。
たとえば、次のトークンは有効であるとみなされます。

 

eyAiYWxnIiA6ICJOb25lIiwgInR5cCIgOiAiSldUIiB9Cg.eyB1c2VyX25hbWUgOiBhZG1pbiB9Cg.

 

これは、単にこれら 2 つの BLOB の Base64URL エンコードされたバージョンであり、署名は存在しなくて。

 

{
"alg" : "none",
"typ" : "JWT"
}
{
"user" : "admin"
}

 

この機能はもともとデバッグ目的で使用されていて。
しかし、運用環境でオフにしないと、攻撃者が alg フィールドを「none」に設定することで、任意のトークンを偽造できるようになり。
その後、偽造したトークンを使用して、サイト上の誰でもなりすますことができ。 

 

2.HMACアルゴリズム

 

JWT に使用されるアルゴリズムの最も一般的なタイプは、HMAC と RSA の 2 つで。 HMAC では、トークンはキーで署名され、後で同じキーで検証され。
RSA の場合、トークンは最初に秘密キーを使用して作成され、次に対応する公開キーで検証され。

 

HMAC -> signed with a key, verified with the same key

RSA -> signed with a private key, verified with the corresponding public key

 

HMAC トークンの秘密キーと RSA トークンの秘密キーはトークンの署名に使用されるため、秘密に保つことが重要で。

ここで、もともとRSA トークンを使用するように設計されたアプリケーションがあるとして。
トークンは秘密鍵 A で署名され、一般には秘密にされます。
次に、誰でも利用できる公開鍵 B を使用してトークンが検証され。
トークンが常に RSA トークンとして扱われる限り、これは問題なくって。

 

Token signed with key A -> Token verified with key B (RSA scenario)

 

ここで、攻撃者が alg を HMAC に変更すると、偽造したトークンに RSA 公開鍵 B で署名することで有効なトークンを作成できる可能性があり。

これは、もともとトークンが RSA で署名されている場合、プログラムは RSA 公開鍵 B を使用して検証するためです。署名アルゴリズムが HMAC に切り替えられても、トークンは依然として RSA 公開鍵 B を使用して検証されますが、今回はトークンが同じ公開鍵 B で署名できます (HMAC を使用しているため)。

 

無効な署名を提供してください

トークンがアプリケーションに到着した後、その署名が検証されない可能性もあり。
この方法では、攻撃者は無効な署名を提供することでセキュリティメカニズムを簡単に回避でき。

 

秘密鍵ブルートフォース攻撃する

JWT の署名に使用されるキーをブルートフォース攻撃することも可能で。

攻撃者は、まず多くの情報を持っていて。
攻撃者は、トークンの署名に使用されたアルゴリズム、署名されたペイロード、および結果の署名を知っていて。
トークンの署名に使用されるキーが十分に複雑でない場合、彼女は簡単にブルート フォース攻撃を実行できる可能性があり。

 

秘密鍵を漏洩する

攻撃者が鍵を総当たり攻撃できない場合、代わりに秘密鍵の漏洩を試みる可能性があり。
攻撃者がキー値が保存されているファイルを読み取ることを可能にする別の脆弱性 (ディレクトリ トラバーサル、XXE、SSRF など) が存在する場合、攻撃者はキーを盗んで任意のトークンに署名する可能性があり。

 

KID の操作

KID は「キー ID」の略で。
これは JWT のオプションのヘッダー フィールドであり、開発者はトークンの検証に使用するキーを指定でき。
KID パラメータの適切な使用法は次のようになり。

 

{
"alg" : "HS256",
"typ" : "JWT",
"kid" : "1"      // use key number 1 to verify the token
}

 

このフィールドはユーザーによって制御されるため、攻撃者によって操作され、危険な結果につながる可能性があります。

 

1. ディレクトリトラバーサル

KID は キー ファイル ファイル システムから取得するためによく使用されるため、使用前にサニタイズしないとディレクトリ トラバーサル攻撃につながる可能性があり。
この場合、攻撃者はファイル システム内の任意のファイルをトークンの検証に使用するキーとして指定できます。

 

“kid”: “../../public/css/main.css
// use the publicly available file main.css to verify the token

 

たとえば、攻撃者はアプリケーションに公開されているファイルをキーとして使用させ、そのファイルを使用して HMAC トークンに署名させることができ。

 

2. SQLインジェクション

KIDはまた、データベースから取得することもできます。
この場合、SQLインジェクションを利用してJWT 署名をバイパスできる可能性が。

KID パラメータで SQL インジェクションが可能な場合、攻撃者はこのインジェクションを使用して、必要な値を返すことができ。

 

“kid”: "aaaaaaa' UNION SELECT 'key';--"

// use the string "key" to verify the token

 

たとえば、上記の注入により、アプリケーションは文字列「key」を返します (「aaaaaa」という名前のキーがデータベースに存在しないため)。
次に、トークンは文字列「key」を秘密鍵として使用して検証され。

 

ヘッダーパラメータの操作

キー ID に加えて、JSON Web トークン標準により、開発者は URL 経由でキーを指定する機能も提供されます。

 

1. JKUヘッダーパラメータ

JKU は 「JWK セット URL」の略で。
これは、トークンの検証に使用されるキーのセットを指す URL を指定するために使用されるオプションのヘッダー フィールドで。
このフィールドが許可されていても適切に制限されていない場合、攻撃者は独自のキー ファイルをホストし、アプリケーションがそれをトークンの検証に使用するように指定する可能性があり。

 

jku URL -> file containing JWK set -> JWK used to verify the token

 

2. JWKヘッダーパラメータ

オプションの JWK (JSON Web Key) ヘッダー パラメーターを使用すると、攻撃者はトークンの検証に使用されるキーをトークンに直接埋め込むことができ。

 

3. X5U、X5C URL操作

jku および jwk ヘッダーと同様に、 x5u および x5c を指定できます 公開キー証明書または証明書チェーン ヘッダー パラメーターを使用すると、攻撃者はトークンの検証に使用され 。
x5u では情報を URI 形式で指定しますが、x5c では証明書の値をトークンに埋め込むことができ。

 

その他の JWT セキュリティ問題

JWT が正しく実装されていない場合に発生する他の問題もあり。
これらはあまり一般的ではありませんが、間違いなく注意する価値があり。

 

情報漏洩

JSON Web トークンはアクセス制御に使用されるため、多くの場合、ユーザーに関する情報が含まれてて。

トークンが暗号化されていない場合、誰でもトークンを Base64 デコードして、トークンのペイロードを読み取ることができ。
そのため、トークンに機密情報が含まれている場合、情報漏洩の原因となる可能性があり。
JSON Web トークンの署名セクションが適切に実装されていると、機密性ではなくデータの整合性が提供され。

 

コマンドインジェクション

KID パラメータが安全でないファイル読み取り操作に直接渡されると、コードフローにコマンドが挿入される可能性があり。

この種の攻撃を許可する可能性のある関数の 1 つは、 Ruby の open() 関数で。
この関数を使用すると、攻撃者は入力の KID ファイル名の後にコマンドを追加するだけでシステム コマンドを実行でき。

 

“key_file” | whoami;

 

これはほんの一例で。
理論的には、アプリケーションがヘッダー パラメーターのいずれかをサニタイズされていない状態で system()、exec() などの関数に渡すと、このような脆弱性が発生する可能性があり。

結局のところ、JSON Web トークンはユーザー入力の別の形式にすぎず。
それらは常に懐疑的な気持ちを持って扱われ、厳密に消毒される必要があり。

 

ほなほな。