JWT, Json Web Token 취약성

11138 단어 webweb

TL;DR

JWT 보안관련 내용을 정리하고자 합니다.

JWT


JSON을 이용한 웹 토큰을 의미합니다. 주로 서버, 클라이언트 등 상호간의 통신 시그니처를 검증하여 위변조 여부 확인, expire값을 통해 만료 여부 확인, CSRF 토큰 등에 사용됩니다.

기본적으로 JWT는 Header + payload + signature로 구성되고 각 필드는 Base64로 인코딩되어 있습니다.

Header

암호화 알고리즘 및 Type을 의미합니다.

{"alg" : "HS256" , "typ" : "jwt"}

alg 는 보안 알고리즘 , typ 는 type을 의미합니다.

Payload

전송할 내용, 사용자가 추가한 데이터 영역

{ “test”:0000001, “User”:“TestUser1”, “auth”:“nomal_user” }

⇒ base64 인코딩 eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwYXJhbTEiOjgwODB9.wNDKI_bZi5E5uWFwQ72QbMUEsn0_mlyT1F2y_0xWSKA

Signature

헤더와 페이로드가 변조되었는지를 검증하기 위한 부분.

서명은 Header + . + Payload 의 값으로 생성합니다.

→ 해당 서명은 Header에 있는 alg 알고리즘으로 암호화하며 변조여부를 판단.

  • Secret key 가 있다면 jwt를 복원할 수 있습니다.

  • JWT는 각 구간별로 Base64로 인코딩 됩니다.

  • JWT는 내용에 대한 서명을 내용 뒤에 붙여, 위변조를 감지할 수 있습니다. secret이 간단하게 설정된 경우에는 secret을 찾고 변조된 JWT를 만들 수 있습니다.

→ 이를 인증에 사용하거나 중요 로직에서 데이터를 읽어 사용하는 경우 보안적인 리스크를 가지게 됩니다.

key rotation (또는 key rolling) 이란?

  • 보호하려고 하는 데이터가 모두 하나의 key로 암호화 되어있는 경우 해당 key가 유출되면 모든 데이터가 유출되게 됩니다. 이러한 위험성을 줄이기 위해서 위해서 주기적으로 key를 변경하는 것을 key rotation 이라고 합니다. 이 경우 특정 key가 유출되더라도, 특정 기간동안에 생성된 데이터만 유출되고, 다른 key로 암호화된 데이터는 안전합니다.
  • 일반적인 인증서의 경우 1~2년 정도의 유효기간을 가지게 됩니다. 인증서 마이그레이션을 위해 보통 구버전의 인증서가 만료되는 시점과 새로운 인증서의 유효기간을 겹치도록 새 인증서를 발급하고, 겹치는 기간동안은 두 인증서를 모두 지원해야 합니다. 결국 인증서도 public key, private key의 조합이기 때문에 이러한 절차도 key rotation이라고 볼 수 있습니다.



JWT관련 취약점


Payload 내 정보 노출

payload 내 중요 정보가 노출되어 있는 취약점이 발생할 수 있습니다.

발생원인

중요 정보를 Payload에 담은 경우
Payload는 Base64 디코딩을 통해 정보를 볼 수 있습니다.

예시

// base64 Payload
eyJuYW1lIjoibWFrZWJyZWFkIiwidXNlcl9uYW1lIjoibWFrM2JyZWFkIiwicGFzc3dvcmQiOiJoaW1ha2VicmVhZCJ9

// decoded Payload
{
  "name": "makebread",
  "user_name": "mak3bread",
  "password": "himakebread"
}


Payload 조작 가능 및 권한 상승

payload를 조작하여, 허가되지 않은 기능을 실행하거나 현재 유저보다 높은 권한을 갖게 되는 취약점 입니다.

발생원인

signature에 대한 검증이 미흡하여, payload가 조작되어도 애플리케이션은 해당 요청에 변조가 없다고 판단

예시

{
  "name": "makebread",
  "user_name": "mak3bread",
  "admin": false
}

payload 데이터에 admin을 의미하는 True/False 값이 있는 경우 해당 토큰 값을 "admin" : true 로 설정하여 인증 우회 및 권한 상승을 할 수 있습니다.



Header key id injection

Header에 key id관련 파라미터가 존재하는 경우, key id부분에서 여러 Injection 취약점이 발생할 수 있습니다.

발생원인

jwt 헤더에는 key id 매개변수가 포함될 수 있습니다.
key id는 보통 데이터 베이스나 파일 시스템에서 키를 검색하는 데 사용됩니다.
key id 파라미터에서의 Injection으로 인하여 다음과 같은 취약점이 발생할 수 있습니다.

  1. Directory Traversal
  2. RCE
  3. SQLI (NoSQLI)

Directory Traversal 예시

key id 파라미터로 파일 시스템에 접근하는 경우, Directory Traversal이 가능할 수 있습니다.

{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "../../../../../../dev/null"
}

RCE 예시

{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "key1|/usr/bin/uname"
}

SQLI 예시

kid 매개변수 삽입을 통한 SQLI

kid를 찾는 방식이

SELECT key FROM keys WHERE key='key1'

라면 다음과 같이 변조 하여 우회할 수 있습니다.

{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "xxxx' UNION SELECT 'aaa"
}

->

SELECT key FROM keys WHERE key='xxxx' UNION SELECT 'aaa'


Header JKU Parameter Attack

JWT의 Header에는 jku 파라미터가 사용될 수 있고, jku 파라미터에서 발생할 수 있는 취약점이 존재합니다.

JKU

JSON Web Key Set URL.
JWT 헤더에서 사용되는 파라미터로 키 검증을 위한 서버를 지정할 수 있다.

{
  "alg": "RS256",
  "typ": "JWT",
  "jku":"https://example.com/key.json"
}

다음과 같이 JWT헤더가 정의되어 있는 경우, key.json 파일에는

{
  "kty": "RSA",
  "n": "-4KIwb83vQMH0YrzE44HppWvyNYmyuznuZPKWFt3e0xmdi-WcgiQZ1TC...RMxYC9lr4ZDp-M0",
  "e": "AQAB"
}

다음과 같은 정보가 저장되어 있고 이를 사용하여 서명을 검증할 수 있습니다.

공격 예시

공격자가 jku 파라미터를 변조할 수 있는 경우, 공격자의 JWK를 카리키는 URL 값을 삽입하여 자신의 키를 사용하여 악의적인 토큰에 서명을 할 수 있습니다. 결과적으로 공격자가 악의적인 JWT를 전송하면, 공격자의 JWK를 가져와 서명을 확인할 수 있게 됩니다.

보통 이러한 공격의 경우, 도메인 검증이나 URL에 대한 필터링을 사용하여 막지만, 이러한 것도 다시 우회될 가능성이 있습니다.

관련 우회

https://truested -> 해당 도메인인지 확인 하는 경우
attacker.com/key.json -> 공격자 JWK

  • open redirect
    https://trusted/jwks/../open_redirect_url=attacker.com

  • starting with trusted로 확인하는 경우
    https://[email protected]
    https://trusted#attacker.com

  • header injection
    https://trusted/jwks/../header_injection



None Algorithm Attack

공격자가 해싱 알고리즘을 'none'으로 변경하여 signature 검증을 우회할 수 있는 취약점.

→ 공격자가 해싱 알고리즘을 none으로 변경하는 것을 의미합니다. 몇몇 라이브러리 들은 none 알고리즘으로 서명된 토큰을 유효한 토큰으로 인식하는 경우가 있습니다. 따라서 공격자가 토큰의 요청을 변조하고 어플리케이션에 의해서 신뢰가 됩니다.

헤더의 alg 값을 none으로 설정한 경우입니다.

{
  "alg": "HS256",
  "typ": "JWT" 
}.
{
  "name": "makebread",
  "user_name": "make.bread",
  "is_admin": false
}.SIGNATURE

다음과 같이 일반적인 JWT에서 공격자가 is_admin 부분을 True로 변경해도 SIGNATURE부분 때문에 유효한 토큰으로 인식되지 않습니다.

{
  "alg": "None",
  "typ": "JWT"
}.
{
  "name": "makebread",
  "user_name": "make.bread",
  "is_admin": true
}.

다음과 같이 alg 부분을 None, none, NONE, nOnE 등으로 설정된다면, SIGNATURE 없이 유효한 토큰으로 인식될 수 있기 때문에, Payload 부분의 is_admin 값을 True로 설정하여 권한 우회가 가능할 수 있습니다.

관련 대응

JWT signature에 사용되는 algorithm이 RSA, EC, HMAC 등으로 지정되야 합니다.



Brute Force Attack

강도가 약한 secret key 사용으로 secret key 노출될 수 있는 취약점입니다.
→ key의 강도가 길이 일 수도 있으므로

예를 들어 1글자 키라면 Brute Force Attack으로 인해 인코딩에 들어간 Secret key 가 노출 될 수 있다.

→ HMAC Secret 브루트포스 공격 가능




참조


좋은 웹페이지 즐겨찾기