설명
JWT를 직접 분리하거나 ReadJwtToken처럼 디코드 전용 API로 읽는 것만으로는 서명이 검증되지 않습니다. 이렇게 얻은 클레임을 인증이나 권한 판단에 신뢰하면 공격자가 위조한 값을 사용할 수 있습니다.
잠재적 영향
- 인증 우회, 권한 상승, 사용자 가장이 발생할 수 있습니다.
해결 방법
JwtSecurityTokenHandler.ValidateToken이나 ASP.NET Core 인증 미들웨어를 사용해 서명, 발급자, 대상, 만료 시간을 검증합니다.
예시
변경 전
csharp
sealed class Jwt
{
public string[] Decode(JwtValidationRequest request)
{
return request.Token.Split('.');
}
}
sealed class JwtValidationRequest
{
public string Token { get; set; } = "";
}
변경 후
키는 신뢰된 설정에서 제공하고 발급자·대상은 실제 서비스 값으로 지정하세요. 검증 실패는 인증 실패로 처리해야 합니다.
csharp
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
ClaimsPrincipal ValidateJwt(string token, SecurityKey trustedSigningKey)
{
var validationParameters = new TokenValidationParameters
{
RequireSignedTokens = true,
ValidateIssuerSigningKey = true,
IssuerSigningKey = trustedSigningKey,
ValidAlgorithms = new[] { SecurityAlgorithms.RsaSha256 },
ValidateIssuer = true,
ValidIssuer = "https://issuer.example.com",
ValidateAudience = true,
ValidAudience = "api://orders",
RequireExpirationTime = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(1)
};
return new JwtSecurityTokenHandler().ValidateToken(
token, validationParameters, out _);
}
설명:
- 변경 전: 문자열 분리는 검증이 아닙니다. 검증되지 않은 토큰의 클레임을 신뢰하면 위조되거나 서명되지 않은 값을 받아들일 수 있습니다.
- 변경 후: 신뢰된 키와 허용 알고리즘을 고정하고 서명, 발급자, 대상, 만료 시간을 모두 검증합니다.
ValidateToken호출만 추가하고 검증 옵션을 약화하면 안전하지 않습니다.