コンテンツにスキップ

Index

安全でないJWT署名の検証

説明

JWTはWebアプリケーションの認証と認可に広く使用されている標準ですが、潜在的なリスクや脆弱性を認識しておくことが重要です。一般的なJWTの脆弱性は次のとおりです。

  • 脆弱な署名アルゴリズム: JWTは通常、トークンの完全性と真正性を保証するために署名を使用します。しかし、脆弱な署名アルゴリズムが使用されたり、署名に使用される秘密鍵が侵害されたりすると、攻撃者がトークンを偽造または改ざんする可能性があります。強力な暗号アルゴリズムを使用し、鍵を適切に保護することが不可欠です。
  • 安全でない鍵管理: JWTは、トークンの真正性を検証するために秘密鍵に依存しています。鍵が適切に管理または保護されていない場合、盗まれたり、漏洩したり、侵害されたりする可能性があります。鍵を安全に保存し、強力な暗号化を使用し、鍵の定期的なローテーションやアクセスの制限など、鍵管理のベストプラクティスに従うことが重要です。
  • トークンの有効期限: JWTは多くの場合、有効性を制限するために有効期限(expクレーム)を持ちます。しかし、有効期限が未来に設定されすぎているか、正しく強制されていない場合、攻撃者が期限切れのトークンを使用して不正アクセスを取得する可能性があります。適切な有効期限を設定し、サーバー側で検証することが不可欠です。
  • トークンの漏洩: JWTが漏洩したり盗まれたりした場合、攻撃者は追加の認証情報を提供することなく、それを使用して正当なユーザーになりすますことができます。これは、トークンが安全でない方法で送信された場合(暗号化されていない接続など)、脆弱な場所(XSS攻撃の被害を受けやすいクライアント側ストレージなど)に保存された場合、またはトークン処理コードに弱点がある場合に発生する可能性があります。
  • 不十分な検証: JWTを検証する際には、トークンの完全性、署名、および関連するクレームをチェックすることが不可欠です。適切な検証を実行しなかったり、重要なチェックを省略したりすると、脆弱性につながる可能性があります。たとえば、攻撃者がトークンのクレームを改ざんして特権を昇格させたり、不正アクセスを取得したりする可能性があります。
  • トークンリプレイ攻撃: JWTはステートレスであり、攻撃者が有効なトークンを傍受して複数回使用するトークンリプレイ攻撃を検出するための組み込みメカニズムを持っていません。nonceやリプレイ検出メカニズムなどの追加の対策を実装することで、この脆弱性を緩和できます。
  • 安全でないクロスオリジンリソース共有(CORS)ポリシー: JWTを受け入れるAPIをホストしているサーバーに安全でないCORSポリシーがある場合、承認されていないドメインがJWTを使用してリクエストを行うことを許可する可能性があり、情報の漏洩や不正アクセスにつながる可能性があります。

推奨事項

JWTの署名の脆弱性を緩和するには、標準化されたJWTライブラリを使用し、それらを適切に設定し、あらゆる操作の前にJWTトークンの署名と有効期限を検証することが不可欠です。

また、secret keyが漏洩するとすべてのセキュリティ対策が無効になる可能性があるため、これを安全に保存することも不可欠です。

import io.jsonwebtoken.JwtException
import io.jsonwebtoken.Jwts
import io.jsonwebtoken.SignatureAlgorithm
import io.jsonwebtoken.security.Keys
import java.security.Key

// Secure JWT validation
fun validateJwt(token: String, secretKey: Key): Boolean {
    try {
        Jwts.parserBuilder()
            .setSigningKey(secretKey)
            .build()
            .parseClaimsJws(token)
        return true // Token is considered valid
    } catch (e: JwtException) {
        return false // Token validation failed
    }
}

fun main() {
    val token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyfQ.4x6fOGYwfFYIQgZepgK1AnbDDr2-TvAp6im0kKk52Es"
    val secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS256) // Generate a secure secret key

    val isValid = validateJwt(token, secretKey)
    if (isValid) {
        println("Token is valid")
        // Proceed with further processing
    } else {
        println("Token validation failed")
        // Handle invalid token
    }
}

この例では、validateJwt関数は入力としてJWTトークンと安全な秘密鍵を受け取ります。jjwtライブラリの Keys.secretKeyFor メソッドは、HS256 アルゴリズムを使用して安全な秘密鍵を生成するために使用されます。

この関数は、Jwts.parserBuilder() メソッドを使用してクレームを解析することにより、トークンの検証を試みます。setSigningKey メソッドは、署名検証用の安全な秘密鍵を設定するために使用されます。これにより、トークンの署名が安全に検証されます。

例外なしでトークンの解析に成功した場合、トークンは有効と見なされます。それ以外の場合、解析プロセス中に JwtException が発生すると、トークンの検証は失敗します。

安全な秘密鍵を使用し、十分なランダム性を持つ鍵を生成し、不正アクセスから保護するなど、鍵管理のベストプラクティスに従うことで、JWT実装のセキュリティを強化できます。

リンク

標準

  • OWASP_MASVS_L1:
    • MSTG_CRYPTO_2
    • MSTG_CRYPTO_3
    • MSTG_CRYPTO_4
  • OWASP_MASVS_L2:
    • MSTG_CRYPTO_2
    • MSTG_CRYPTO_3
    • MSTG_CRYPTO_4
  • CWE_TOP_25:
  • GDPR:
    • ART_5
    • ART_32
  • PCI_STANDARDS:
    • REQ_2_2
    • REQ_3_6
    • REQ_3_7
    • REQ_6_2
    • REQ_6_3
    • REQ_7_3
    • REQ_8_3
    • REQ_11_3
  • OWASP_MASVS_v2_1:
    • MASVS_CRYPTO_1
    • MASVS_CRYPTO_2
  • SOC2_CONTROLS:
    • CC_2_1
    • CC_3_4
    • CC_4_1
    • CC_7_1
    • CC_7_2
    • CC_7_4
    • CC_7_5
  • CNIL_FOR_DEVELOPERS:
    • DEVELOPERS_4_1_4
  • HIPAA_CONTROLS:
    • SECURITY251
    • SECURITY212
    • SECURITY213