
가상의 JWT 취약점을 확인하기 위한 간단한 파이썬 스크립트
가상의 JWT 취약점을 확인하는 간단한 파이썬 스크립트입니다.
HS256 알고리즘으로 서명된 JWT 토큰을 사용하는 애플리케이션이 있다고 가정해 보겠습니다. 예시 토큰은 다음과 같습니다:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.zbgd5BNF1cqQ_prCEqIvBTjSxMS8bDLnJAE_wE-0Cxg
위 토큰은 다음과 같이 디코딩될 수 있습니다:
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
서명을 계산하기 위해 다음 비밀이 사용됩니다:
supersecret
서명을 계산하는 데 사용되는 의사 코드는 다음과 같습니다:
$alg = "sha256";
$data = "...";
$key = "supersecret";
hmac($alg, $data, $key);
하지만 예상치 못한 "kid":0 필드가 헤더에 주입되면 어떻게 될까요?
{
"alg": "HS256",
"typ": "JWT",
"kid": 0
}
{
"sub": "1234567890",
"name": "John Doe",
"iat": 1516239022
}
kid 필드는 키를 선택하는 표준적인 방법입니다. 제 가정은 kid 필드가 예상되지 않을 경우, $key 문자열 값을 배열로 처리하는 취약한 구현이 있을 수 있다는 것입니다:
hmac($alg, $data, $key[kid]);
그 결과 's'($key[0]) 값이 HMAC 비밀로 사용됩니다.
injector.py 스크립트는 원래 JWT 토큰을 받아서, 헤더에 "kid":0 필드를 주입하고 한 글자 비밀로 서명된 토큰을 생성합니다 (ASCII 코드: 32 - 126 [{space}, !, ", #, ..., x, y, z, {, |, }, ~]):
python3 injector.py eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.zbgd5BNF1cqQ_prCEqIvBTjSxMS8bDLnJAE_wE-0Cxg
결과적으로 tokens.txt와 tokens_meta.txt 두 개의 파일이 생성됩니다. tokens.txt에는 생성된 토큰이 포함되어 있으며 Burp Intruder의 페이로드 목록으로 사용할 수 있습니다. 만약 어떤 토큰이 유효하다면 (이는 애플리케이션이 취약하다는 의미입니다), tokens_meta.txt 파일을 사용하여 해당 토큰을 생성하는 데 사용된 알고리즘과 비밀을 확인할 수 있습니다. tokens_meta.txt 파일에는 다음 데이터가 포함됩니다:
token1:algorithm:secret
...
token{n}:algorithm:secret
자세한 내용은 CHANGELOG를 참조하십시오.