| RFC 8725 | JWT BCP | 2020년 2월 |
| Sheffer 외 | 최선의 현재 관행 | [Page] |
JSON 웹 토큰(JSON Web Tokens, JWT로도 알려짐)은 URL 안전 JSON 기반 보안 토큰으로, 서명 및/또는 암호화될 수 있는 일련의 클레임(claims)을 포함합니다. JWT는 디지털 신원 영역뿐만 아니라 기타 애플리케이션 영역에서도 여러 프로토콜과 애플리케이션에서 간단한 보안 토큰 형식으로 널리 사용되고 있습니다. 이 최선의 현재 관행 문서는 RFC 7519를 업데이트하여 JWT의 안전한 구현 및 배포를 위한 실행 가능한 지침을 제공합니다.¶
이 메모는 인터넷 최선의 현재 관행을 문서화합니다.¶
이 문서는 인터넷 엔지니어링 태스크 포스(IETF)의 산출물입니다. IETF 커뮤니티의 합의를 나타냅니다. 공개 검토를 거쳤으며 인터넷 엔지니어링 관리 그룹(IESG)에 의해 발행 승인을 받았습니다. BCP에 대한 추가 정보는 RFC 7841의 2절에서 확인할 수 있습니다.¶
이 문서의 현재 상태, 오류 정정 사항, 피드백 제공 방법에 대한 정보는 https://www.rfc-editor.org/info/rfc8725에서 확인할 수 있습니다.¶
Copyright (c) 2020 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.¶
JSON Web Tokens, JWT라고도 알려진 [RFC7519], 서명 및/또는 암호화될 수 있는 일련의 클레임을 포함하는 URL 안전 JSON 기반 보안 토큰입니다. JWT 사양은 보안 관련 정보를 하나의 보호하기 쉬운 위치에 캡슐화하고, 널리 사용 가능한 도구를 이용해 쉽게 구현할 수 있기 때문에 빠르게 채택되었습니다. JWT가 일반적으로 사용되는 한 응용 분야는 디지털 신원 정보를 나타내는 것이며, 예를 들어 OpenID Connect ID 토큰 [OpenID.Core] 및 OAuth 2.0 [RFC6749] 액세스 토큰과 리프레시 토큰이 있습니다. 이들의 세부 사항은 배포 환경에 따라 다릅니다.¶
JWT 사양이 발표된 이후, 구현 및 배포에 대한 여러 널리 알려진 공격 사례가 있었습니다. 이러한 공격은 명세가 충분하지 않은 보안 메커니즘, 불완전한 구현, 그리고 애플리케이션에서의 잘못된 사용으로 인해 발생합니다.¶
이 문서의 목표는 JWT의 안전한 구현 및 배포를 촉진하는 것입니다. 본 문서의 많은 권고 사항은 JSON Web Signature (JWS) [RFC7515], JSON Web Encryption (JWE) [RFC7516], JSON Web Algorithms (JWA) [RFC7518]에 정의된 JWT 기반 암호화 메커니즘의 구현 및 사용과 관련이 있습니다. 그 외 일부 권고 사항은 JWT 클레임 자체의 사용과 관련이 있습니다.¶
이 권고 사항은 대부분의 구현 및 배포 시나리오에서 JWT 사용을 위한 최소한의 권장 사항입니다. 이 문서를 참조하는 다른 명세는 특정 상황에 따라 형식의 하나 이상의 측면과 관련된 더 엄격한 요구 사항을 가질 수 있으며, 이 경우 구현자는 해당 엄격한 요구 사항을 준수하는 것이 권장됩니다. 또한 본 문서는 상한이 아닌 하한을 제공하므로, 더 강력한 옵션도 항상 허용됩니다 (예: 암호 강도와 연산 부하의 중요성 평가가 다를 경우).¶
다양한 알고리즘의 강도와 가능한 공격에 대한 커뮤니티 지식은 빠르게 변할 수 있으며, 경험상 보안 관련 Best Current Practice(BCP) 문서는 특정 시점의 진술입니다. 독자는 이 문서에 적용되는 오류 정정이나 업데이트를 확인하는 것이 좋습니다.¶
이 문서에서의 핵심 단어 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", "OPTIONAL"은 모두 대문자로 사용될 때만 BCP 14 [RFC2119] [RFC8174]에서 설명된 대로 해석되어야 합니다.¶
이 섹션에서는 JWT 구현 및 배포와 관련된 알려진 문제와 가능한 문제들을 나열합니다. 각 문제 설명 후에는 해당 문제에 대한 하나 이상의 완화 방법 참조가 이어집니다.¶
서명된 JSON Web Tokens는 암호화 민첩성을 위해 "alg" 헤더 파라미터 형태로 서명 알고리즘을 명시적으로 나타냅니다. 일부 라이브러리와 애플리케이션의 설계 결함과 결합되어 여러 공격이 발생했습니다.¶
또한 일부 애플리케이션은 "HS256"과 같은 키드 메시지 인증 코드(MAC) 알고리즘을 사용하여 토큰에 서명하지만, 불충분한 엔트로피를 가진 약한 대칭 키(예: 사람이 기억할 수 있는 비밀번호)를 제공합니다. 이러한 키는 공격자가 토큰을 입수하면 오프라인 브루트 포스 또는 사전 공격에 취약합니다 [Langkemper].¶
JWE로 암호화된 JWT를 복호화하여 JWS 서명 객체를 얻는 일부 라이브러리는 내부 서명을 항상 검증하지 않습니다.¶
많은 암호화 알고리즘은 평문의 길이에 대한 정보를 유출하며, 유출 정도는 알고리즘과 동작 모드에 따라 달라집니다. 평문이 처음에 압축될 경우 이 문제는 더욱 심각해집니다. 압축된 평문과 암호문의 길이는 원본 평문의 길이뿐만 아니라 내용에도 의존하기 때문입니다. 공격자가 비밀 데이터와 같은 압축 공간에 데이터를 제어할 수 있는 경우, 압축 공격은 특히 강력하며, 이는 HTTPS 공격의 일부 사례에서 나타납니다.¶
압축과 암호화에 대한 일반적 배경은 [Kelsey]를, HTTP 쿠키 공격의 구체적 예는 [Alawatugoda]를 참조하십시오.¶
[Sanso]에 따르면, 여러 자바스크립트 JOSE 라이브러리는 타원곡선 키 합의(ECDH-ES 알고리즘)를 수행할 때 입력값을 올바르게 검증하지 않습니다. 공격자가 유효하지 않은 곡선 점을 사용하는 JWEs를 전송하고, 복호화 후 평문 출력에서 유효하지 않은 곡선 점을 관찰할 수 있다면, 이 취약점을 이용하여 수신자의 개인 키를 회수할 수 있습니다.¶
이전 JSON 포맷 버전, 예를 들어 더 이상 사용되지 않는 [RFC7159], 은 UTF-8, UTF-16, UTF-32 등 여러 문자 인코딩을 허용했습니다. 최신 표준 [RFC8259]에서는 "폐쇄된 생태계" 내부 사용을 제외하고 UTF-8만 허용됩니다. 이전 구현 및 폐쇄 환경에서 사용되는 구현이 비표준 인코딩을 생성할 수 있는 모호성으로 인해, 수신자가 JWT를 잘못 해석할 수 있습니다. 이는 악의적인 발신자가 수신자의 검증을 우회하는 데 악용될 수 있습니다.¶
수신자가 특정 JWT를 받았으나, 이를 다른 수신자에게 사용하려는 공격이 있습니다. 예를 들어, OAuth 2.0 [RFC6749] 액세스 토큰이 원래 의도된 OAuth 2.0 보호 리소스에 합법적으로 제출되었을 때, 해당 보호 리소스가 같은 액세스 토큰을 다른 보호 리소스에 제출하려고 시도할 수 있습니다. 이런 상황을 감지하지 못하면, 공격자가 권한 없는 리소스에 접근할 수 있습니다.¶
JWT가 다양한 프로토콜과 응용 분야에서 사용됨에 따라, 한 목적을 위해 발급된 JWT가 다른 용도로 악용되는 사례를 방지하는 것이 점점 중요해지고 있습니다. 이는 특정 유형의 대체 공격입니다. JWT가 다른 유형의 JWT와 혼동될 수 있는 응용 환경에서 사용될 수 있다면, 이러한 대체 공격을 방지하기 위해 완화 조치 MUST가 필요합니다.¶
다양한 JWT 클레임은 수신자가 데이터베이스 검색이나 LDAP 검색과 같은 조회 작업을 수행하는 데 사용됩니다. 다른 클레임은 서버가 유사하게 조회하는 URL을 포함합니다. 공격자는 이러한 클레임을 주입 공격 또는 서버 측 요청 위조(SSRF) 공격의 벡터로 사용할 수 있습니다.¶
아래에 나열된 권장 사항은 실무자들이 앞 섹션에 나열된 위협을 완화하기 위해 적용해야 합니다.¶
라이브러리는 반드시 호출자가 지원되는 알고리즘 집합을 지정할 수 있게 해야 하며, 다른 알고리즘을 사용해서는 안됩니다 암호화 연산을 수행할 때는 어떠한 다른 알고리즘도 사용해서는 안됩니다. 라이브러리는 "alg" 또는 "enc" 헤더가 암호화 연산에 사용된 동일한 알고리즘을 지정하도록 반드시 보장해야 합니다. 또한, 각 키는 반드시 정확히 하나의 알고리즘과 함께 사용되어야 하며, 암호화 연산이 수행될 때 이 점을 반드시 확인해야 합니다.¶
As Section 5.2 of [RFC7515] 에서 말하듯이, "어떤 알고리즘이 특정 문맥에서 사용될 수 있는지는 애플리케이션의 결정입니다. JWS가 성공적으로 검증될 수 있다 하더라도, JWS에서 사용된 알고리즘이 애플리케이션에 받아들여지지 않는다면, 애플리케이션은 그 JWS를 무효로 간주해야 합니다."¶
따라서, 애플리케이션은 암호학적으로 최신이며 애플리케이션의 보안 요구사항을 충족하는 알고리즘의 사용만 반드시 허용해야 합니다. 새로운 알고리즘이 도입되고 기존 알고리즘이 발견된 암호학적 약점으로 인해 폐기됨에 따라, 이 집합은 시간이 지남에 따라 변경될 수 있습니다. 따라서 애플리케이션은 암호학적 유연성(cryptographic agility)을 가능하게 하도록 설계되어야 합니다.¶
즉, JWT가 TLS와 같은 전송 계층에 의해 종단 간으로 암호학적으로 보호되고 해당 전송 계층이 암호학적으로 최신 알고리즘을 사용한다면, JWT에 대해 추가적인 암호화 보호를 적용할 필요가 없을 수 있습니다. 이러한 경우 "none" 알고리즘의 사용은 완전히 허용될 수 있습니다. "none" 알고리즘은 JWT가 다른 수단으로 암호학적으로 보호되는 경우에만 사용되어야 합니다. "none"을 사용하는 JWT는 콘텐츠의 서명이 선택적인 애플리케이션 문맥에서 자주 사용됩니다; 이때 URL-안전 클레임 표현 및 처리는 서명된 경우와 서명되지 않은 경우 모두에서 동일할 수 있습니다. JWT 라이브러리는 호출자가 명시적으로 요청하지 않는 한 "none"을 사용한 JWT를 생성해서는 안됩니다. 마찬가지로, JWT 라이브러리는 호출자가 명시적으로 요청하지 않는 한 "none"을 사용하는 JWT를 소비해서는 안됩니다.¶
애플리케이션은 다음과 같은 알고리즘별 권고사항을 따라야 합니다:¶
JWT에 사용되는 모든 암호 연산은 반드시 검증되어야 하며, 이들 중 어느 하나라도 검증에 실패하면 전체 JWT를 반드시 거부해야 합니다. 이는 단일 헤더 파라미터 집합을 가진 JWT뿐만 아니라, 외부 및 내부 연산이 모두 포함된 네스티드(Nested) JWT에도 해당하며, 애플리케이션이 제공한 키와 알고리즘을 사용하여 모두 검증되어야 합니다.¶
타원 곡선 디피-헬만 키 교환("ECDH-ES")과 같은 일부 암호 연산은 지정된 타원 곡선 위에 있지 않은 점이나 기타 유효하지 않은 점(예: [Valenta], Section 7.1)과 같이 잘못된 값을 포함할 수 있는 입력을 받습니다. JWS/JWE 라이브러리 자체가 이러한 입력을 사용하기 전에 검증해야 하거나, 또는 이러한 검증을 수행하는 하위 암호화 라이브러리를 사용해야 합니다(또는 둘 다).¶
타원 곡선 디피-헬만 Ephemeral Static(ECDH-ES)의 임시 공개키(epk) 입력은 수신자가 선택한 타원 곡선에 따라 검증되어야 합니다. NIST의 소수 차수 곡선인 P-256, P-384, 및 P-521의 경우, 검증은 "Recommendation for Pair-Wise Key-Establishment Schemes Using Discrete Logarithm Cryptography"의 섹션 5.6.2.3.4 (ECC Partial Public-Key Validation Routine)에 따라 반드시 수행되어야 합니다 [nist-sp-800-56a-r3]. "X25519" 또는 "X448" [RFC8037] 알고리즘이 사용되는 경우에는, [RFC8037]의 보안 고려사항이 적용됩니다.¶
[Section 10.1 of [RFC7515]의 키 엔트로피 및 무작위 값에 관한 조언과, [Section 8.8 of [RFC7518]의 비밀번호 고려사항을 반드시 따라야 합니다. 특히, 사람이 기억할 수 있는 비밀번호를 "HS256"과 같은 키드-MAC 알고리즘의 키로 직접 사용하는 것은 금지되어야 합니다. 또한, 비밀번호는 콘텐츠 암호화보다는 키 암호화를 수행하는 데만 사용해야 하며, 이는 [Section 4.8 of [RFC7518]]에 설명되어 있습니다. 키 암호화에 사용되는 경우에도, 비밀번호 기반 암호화는 여전히 무차별 대입 공격의 대상이 될 수 있습니다.¶
데이터의 압축은 암호화 전에 수행해서는 안됩니다, 왜냐하면 그러한 압축된 데이터는 종종 평문에 대한 정보를 드러내기 때문입니다.¶
[RFC7515], [RFC7516], 및 [RFC7519]은 모두 헤더 파라미터와 JWT 클레임셋에 사용되는 JSON의 인코딩 및 디코딩에 UTF-8을 사용해야 한다고 규정하고 있습니다. 이는 최신 JSON 규격인 [RFC8259]과도 일치합니다. 구현체와 애플리케이션은 반드시 이를 준수해야 하며 이러한 목적을 위해 다른 유니코드 인코딩을 사용하거나 허용해서는 안 됩니다.¶
JWT에 "iss"(발급자) 클레임이 포함된 경우, 애플리케이션은 JWT의 암호 연산에 사용된 암호화 키가 해당 발급자에 속하는지 반드시 검증해야 합니다. 그렇지 않다면 애플리케이션은 해당 JWT를 반드시 거부해야 합니다.¶
발급자가 소유한 키를 결정하는 수단은 애플리케이션마다 다릅니다. 예를 들어, OpenID Connect [OpenID.Core]에서 발급자 값은 "https" URL로, 해당 URL은 "jwks_uri" 값을 포함하는 JSON 메타데이터 문서를 참조하며, 이 "jwks_uri"는 발급자의 키를 JWK 세트로 검색할 수 있는 "https" URL입니다 [RFC7517]. 이와 동일한 메커니즘은 [RFC8414]에서도 사용됩니다. 다른 애플리케이션은 발급자에 키를 바인딩하는 다른 수단을 사용할 수 있습니다.¶
마찬가지로, JWT에 "sub"(주체) 클레임이 포함된 경우, 애플리케이션은 주체 값이 애플리케이션에서 유효한 주체 및/또는 발급자-주체 쌍에 해당하는지 반드시 검증해야 합니다. 여기에는 발급자가 애플리케이션에서 신뢰할 수 있는지 확인하는 것이 포함될 수 있습니다. 발급자, 주체 또는 그 쌍이 유효하지 않다면 애플리케이션은 해당 JWT를 반드시 거부해야 합니다.¶
동일한 발급자가 둘 이상의 의존 당사자나 애플리케이션에서 사용하기 위해 JWT를 발급할 수 있는 경우, JWT에는 JWT가 의도된 당사자에 의해 사용되고 있는지 혹은 공격자에 의해 의도되지 않은 당사자에 대체되었는지를 판단할 수 있는 "aud"(수신자) 클레임을 포함해야 합니다.¶
이러한 경우 의존 당사자나 애플리케이션은 수신자 값을 반드시 검증해야 하며, 수신자 값이 존재하지 않거나 수신자와 연관되어 있지 않다면 해당 JWT를 반드시 거부해야 합니다.¶
"kid"(키 ID) 헤더는 의존 애플리케이션이 키 조회를 수행하는 데 사용됩니다. 애플리케이션은 수신된 값이 SQL 또는 LDAP 인젝션 취약점을 초래하지 않도록 해당 값을 검증 및/또는 정제해야 합니다.¶
마찬가지로, 임의의 URL을 포함할 수 있는 "jku"(JWK 세트 URL) 또는 "x5u"(X.509 URL) 헤더를 맹목적으로 따르는 것은 서버 측 요청 위조(SSRF) 공격을 초래할 수 있습니다. 애플리케이션은 이러한 공격으로부터 보호해야 하며, 예를 들어 URL을 허용된 위치의 화이트리스트와 대조하고 GET 요청에 쿠키가 전송되지 않도록 보장하는 등의 조치를 취해야 합니다.¶
때로는 한 종류의 JWT가 다른 종류로 혼동될 수 있습니다. 특정 종류의 JWT가 이러한 혼동의 대상이라면, 해당 JWT는 명시적인 JWT 타입 값을 포함할 수 있고 검증 규칙은 타입 확인을 지정할 수 있습니다. 이 메커니즘은 이러한 혼동을 방지할 수 있습니다. 명시적 JWT 타입 지정은 "typ" 헤더 파라미터를 사용하여 수행됩니다. 예를 들어, [RFC8417] 명세는 Security Event Tokens(SETs)의 명시적 타입 지정을 위해 "application/secevent+jwt" 미디어 타입을 사용합니다.¶
"typ"의 정의에 따라 Section 4.1.9 of [RFC7515], "typ" 값에서 "application/" 접두어를 생략하는 것이 권장됩니다. 따라서 예를 들어, SET의 타입을 명시적으로 포함하기 위해 사용되는 "typ" 값은 "secevent+jwt"가 되어야 합니다. JWT에 대해 명시적 타입 지정을 적용할 때, 미디어 타입 이름 형식으로 "application/example+jwt"를 사용하는 것이 권장되며, 여기서 "example"은 특정 JWT 종류의 식별자로 대체됩니다.¶
네스티드 JWT에 명시적 타입 지정을 적용할 때, 명시적 타입 값을 포함하는 "typ" 헤더 파라미터는 네스티드 JWT의 내부 JWT(페이로드가 JWT 클레임셋인 JWT)에 반드시 있어야 합니다. 경우에 따라 동일한 "typ" 헤더 파라미터 값이 외부 JWT에도 존재하여 전체 네스티드 JWT를 명시적으로 타입 지정할 수 있습니다.¶
명시적 타입 사용이 기존 종류의 JWT와의 혼동을 완전히 해소하지 못할 수 있다는 점에 유의하십시오, 기존 종류의 JWT에 대한 검증 규칙이 종종 "typ" 헤더 파라미터 값을 사용하지 않기 때문입니다. 새로운 JWT 용도에 대해서는 명시적 타입 지정을 권장합니다.¶
각 JWT 적용은 필수 및 선택적 JWT 클레임과 이와 관련된 검증 규칙을 지정하는 프로필을 정의합니다. 동일한 발급자가 둘 이상의 종류의 JWT를 발급할 수 있는 경우, 해당 JWT들에 대한 검증 규칙은 서로 배타적이 되도록 반드시 작성되어야 하며, 잘못된 종류의 JWT는 거부해야 합니다. 한 문맥의 JWT가 다른 문맥으로 대체되는 것을 방지하기 위해 애플리케이션 개발자는 여러 전략을 사용할 수 있습니다:¶
JWT 사용 및 애플리케이션의 광범위한 다양성을 고려할 때, 서로 다른 종류의 JWT를 구별하기 위한 타입, 필수 클레임, 값, 헤더 파라미터, 키 사용법 및 발급자의 최적 조합은 일반적으로 애플리케이션별일 것입니다. 섹션 3.11에서 논의한 바와 같이, 새로운 JWT 애플리케이션의 경우 명시적 타입 사용이 권장됩니다.¶
"ECDH-ES" 잘못된 점 공격을 JWE 및 JWT 구현자들에게 알려준 Antonio Sanso에게 감사드립니다. RSA/HMAC 혼동 공격을 발표한 것은 Tim McLean입니다 [McLean]. 명시적 타입 사용을 옹호해 준 Nat Sakimura에게 감사드립니다. 수많은 의견을 제공해 준 Neil Madden에게 감사드리며, 검토를 해 준 Carsten Bormann, Brian Campbell, Brian Carpenter, Alissa Cooper, Roman Danyliw, Ben Kaduk, Mirja Kühlewind, Barry Leiba, Eric Rescorla, Adam Roach, Martin Vigoureux, and Éric Vyncke 에게 감사드립니다.¶