JWT 서명 검증 누락
Missing JWT Signature Verification
설명
애플리케이션이 JWT를 파싱할 때 서명을 강제로 검증하지 않는 parse API를 사용하면, alg=none 등 서명이 없는 토큰도 그대로 수용될 수 있습니다. 공격자는 임의로 header와 claims를 구성해 토큰을 만들고, 서명 없이도 애플리케이션이 신뢰하도록 속일 수 있습니다. 이를 악용해 인증을 우회하거나 더 높은 권한의 사용자로 가장하는 공격이 가능합니다.
잠재적 영향
인증 우회 (Authentication Bypass): 서명이 없는 임의의 토큰으로 로그인 절차를 통과해 보호 리소스에 접근할 수 있습니다.
권한 상승 (Privilege Escalation): 관리자 등의 권한을 claim에 임의로 넣어 높은 권한 기능을 실행할 수 있습니다.
데이터 유출 (Data Exposure): 접근 제어가 필요한 사용자 정보나 내부 API 응답을 무단 조회할 수 있습니다.
계정 탈취 (Account Takeover): 특정 사용자의 sub/uid를 위조해 그 사용자의 세션처럼 행동할 수 있습니다.
해결 방법
서명 검증을 강제하는 API 사용: Jwts.parserBuilder().setSigningKey(...).build().parseClaimsJws(token) 또는 parsePlaintextJws(token)를 사용합니다.
Handler 사용 시 안전 경로만 처리: parse(token, handler)를 쓸 경우 onClaimsJws 또는 onPlaintextJws만 오버라이드하여 처리하고, onPlaintextJwt는 사용하지 않습니다.
키 구성: setSigningKey 또는 setSigningKeyResolver를 반드시 설정하고, 검증 실패 시 요청을 거부합니다.
알고리즘 정책: 허용할 알고리즘을 제한하고, alg=none을 거부하도록 설정/검증 로직을 추가합니다.
추가 검증: 만료(exp), 발행자(iss), audience(aud) 등 주요 claim을 검증하고, 예외 발생 시 즉시 인증 실패로 처리합니다.
라이브러리 최신화: jjwt를 최신 버전으로 유지하고 보안 패치를 적용합니다.
취약한 코드 및 안전한 코드 예시
취약한 코드
안전한 코드
설명:
취약한 코드: parse(token)을 사용하면 jjwt가 서명 유무를 강제하지 않아 alg=none 같은 서명 없는 토큰도 통과할 수 있습니다. 이 상태에서 body를 신뢰하면 공격자가 임의로 만든 토큰으로 인증을 우회할 수 있습니다.
안전한 코드: parseClaimsJws(token)은 JWS 서명 검증을 필수로 수행합니다. 키가 맞지 않거나 서명이 없으면 예외가 발생해 요청이 거부됩니다. 추가로 발행자 등 claim을 검증해 위조 토큰을 더 확실히 차단합니다.
참조
Last updated