JWT 로컬 분석
실습 토큰의 Header·Payload를 로컬에서 읽고 서명 검증과 구별합니다.
Python 표준 라이브러리 사용 · 외부 디코더 불필요실습 범위
이 사이트의 JWT 문제에서 발급된 교육용 토큰만 로컬에서 분석하세요. Header·Payload 디코딩은 서명 검증이 아닙니다. 실제 서비스의 토큰·쿠키·FLAG 원문은 외부 도구나 공개 문서에 올리지 마세요.
분석 준비
JWT 형식 표준 (RFC 7519) ↗ JWT 형식의 표준 문서입니다. 설치 파일은 필요하지 않습니다.
1. 실습 토큰만 선택
JWT 문제에서 제공된 교육용 토큰을 사용합니다. 자신의 실제 로그인 토큰이나 다른 서비스의 세션은 공개 웹 디코더에 붙여 넣지 마세요. 토큰을 분석 기록에 그대로 남기지 않습니다.
2. 준비 도구
앞의 Python 안내대로 설치했으면 표준 라이브러리만으로 Header·Payload를 읽을 수 있습니다. Burp Suite가 있다면 Decoder의 Base64 URL-safe 변환으로도 확인할 수 있습니다. 별도의 온라인 JWT 사이트는 필요하지 않습니다.
처음부터 따라 하기
- 01
세 부분 분리
JWS Compact 형식의 실습 토큰은 점으로 구분된 Header.Payload.Signature입니다. 점이 두 개가 아니면 이 예제로 해석하지 마세요. 각 부분을 수정하면 원래 서명은 유효하지 않게 됩니다.
- 02
로컬에서 Header·Payload 보기
아래 내용을 jwt_read.py로 저장하고 터미널에서 python jwt_read.py 또는 Windows의 py jwt_read.py로 실행합니다. 입력 프롬프트에 교육용 토큰을 붙여 넣습니다. 이 코드는 디코딩만 하고 서명은 검증하지 않습니다.
import base64 import json token = input('실습 JWT: ').strip() parts = token.split('.') if len(parts) != 3: raise ValueError('JWS Compact 형식이 아닙니다') for label, part in zip(('Header', 'Payload'), parts[:2]): raw = base64.urlsafe_b64decode(part + '=' * (-len(part) % 4)) print(label, json.dumps(json.loads(raw), ensure_ascii=False, indent=2)) print('서명 검증: 수행하지 않음') - 03
클레임을 읽되 신뢰하지 않기
Header의 alg, Payload의 sub·name·team·role·exp 등을 확인합니다. 이 사이트의 JWT 문제에서 name=rok, team=roksec처럼 보이더라도 이는 페이로드의 표시 값일 뿐입니다. 서버가 허용 알고리즘·서명·만료·발급자/대상 정책과 자원별 인가를 확인해야 신뢰할 수 있습니다.
- 04
문제에서 검증 경계 찾기
토큰이 어디서 발급되고 쿠키나 Authorization 헤더 중 어디로 전달되는지 Burp/DevTools로 관찰합니다. 페이로드 변조만으로 권한이 바뀌는지, 서명키 취약점인지, 검증 누락인지 서로 다른 원인으로 구별하세요.
성공하면 무엇이 보이나요?
- Header·Payload·Signature 세 부분의 존재
- Base64url 디코딩은 복호화도 서명 검증도 아니라는 점
- 서버가 실제로 검사하는 클레임과 인가 조건
실습 기록
실습 토큰의 클레임 이름만 요약하고, 디코딩으로 알 수 있는 정보와 서버 검증이 필요한 판단을 두 칸으로 나누어 기록하세요.
막힐 때 확인하기
점으로 나뉘지 않음
JWT가 아닌 쿠키나 접두어(Bearer)를 함께 복사하지 않았는지 확인하세요.
JSON 디코딩 오류
토큰 일부가 잘렸거나 JWS Compact 형식이 아닐 수 있습니다. 실제 비밀 토큰을 온라인 서비스에 보내 디버깅하지 마세요.
Payload를 바꿨는데 인증 실패
정상적인 서명 검증이라면 당연한 결과입니다. 단순 Base64url 인코딩은 새 유효 서명을 만들지 않습니다.
표준·공식 설명서
형식 표준과 도구 설명서를 구분해 확인하세요. 이 수업의 로컬 분석에는 별도 JWT 설치 파일이 필요하지 않습니다.