Skip to main content

Command Palette

Search for a command to run...

(취약점 제거됨) Spring Boot: 2024 JJWT 취약점(v0.12.5 이하) 및 'signWith(java.security.Key, io.jsonwebtoken.SignatureAlgorithm)' is deprecated 해결 (v0.12.0 이상)

다 방법이 있습니다.

Updated
(취약점 제거됨) Spring Boot: 2024 JJWT 취약점(v0.12.5 이하) 및 'signWith(java.security.Key, io.jsonwebtoken.SignatureAlgorithm)' is deprecated 해결 (v0.12.0 이상)
M

Hello, I am Korean. Welcome, visitor. You are very cool. 안녕하세요, 저는 한국어입니다. 방문자여 환영한다. 당신은 매우 시원해.

JJWT Impl의 취약점 발견

취약점 보고(CVE)

참고: signWith() 함수의 deprecated는 0.12.0 버전에 되어 CVE 보고와 무관합니다. 취약점은 사소한 것이며, 0.11 버전 이하를 사용하더라도 반드시 올려야 하는 것은 아닙니다.
벤더 측에서 릴리스한 버전을 권장하기 위하여 정보를 공유합니다.

해당 취약점은 CVE에 CVE-2024-31033로 보고되었습니다. (2024-03-27, 논쟁 있음)

이 보고의 내용은 이렇습니다. (논쟁)

0.12.5 이하 JJWT(Java JWT)는 특정 문자를 무시하므로 사용자에게 강력한 키(key)가 있다고 잘못 판단했을 수 있습니다.

JJWT 공급자는 다음처럼 이의를 제기합니다.

JJWT 사용 방식에서 사용자의 오류가 없는 한 '무시(ignores)' 동작이 어떤 버전에서도 발생할 수 없으며, 실제 테스트된 버전은 6년 이상 지나야 하기 때문에 이의를 제기하고 있습니다.

이 취약점의 영향을 받는 코드는 다음과 같습니다.

  • DefaultJwtParser 클래스 내의 setSigningKey() 메서드

  • DefaultJwtBuilder 클래스 내의 signWith() 메서드

새 버전 릴리스

MVN Repository에서 다음처럼 0.12.5 이하 버전은 모두 취약점 하나가 체크되어 있으며, 올해 6월 21일에 그 다음 버전인 0.12.6 버전이 릴리스되었습니다.


새 버전에서 유효한 방식 (v0.12.0 이상)

의존성 추가

다음처럼 v0.12.6으로 의존성을 추가합니다.

// build.gradle에서 관련 모듈의 dependencies
dependencies {
    // jjwt
    implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'
}

JWT Provider 작성

deprecated 예시

// 0.11 버전에서 deprecated 되었습니다.
// (io.jsonwebtoken.SignatureAlgorithm, String)
.signWith(SignatureAlgorithm.HS256, secret)

// 0.12.0 버전에서 deprecated 되었습니다.
// (java.security.Key, io.jsonwebtoken.SignatureAlgorithm)
.signWith(secretKey, SignatureAlgorithm.HS256)

유효한 함수 (기본 알고리즘: HS256)

// signWith(java.security.Key)
.signWith(secretKey)

전체 코드 예시 (generateToken() 함수 위주로 보세요.)

import example.demo.common.jwt.properties.DemoJwtProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.stereotype.Component;

import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component
public class JwtProvider {

    private final Key secretKey;
    private final long maxAge;

    // 구성 속성을 받아 올 때는 편한 방식(@Value 등)을 사용하면 됩니다.
    public JwtProvider(DemoJwtProperties demoJwtProperties) {
        secretKey = generateSecretKey(demoJwtProperties.secret());
        maxAge = demoJwtProperties.maxAge();
    }

    @Override
    public String generateToken(String subject, Map<String, ?> payload) {
        // header, payload, signature -> base64
        Claims claims = generateClaims(subject, payload);

        return Jwts.builder()
                .signWith(secretKey)
                .claims(claims)
                .compact();
    }

    // DemoJwtProperties 파일에 작성할 수도 있지만, 속성 파일에 외부 기술에 대한 종속성을 만들지 않기 위해 여기서 작성.
    private Key generateSecretKey(String secret) {
        byte[] keyBytes = Decoders.BASE64.decode(secret);
        return Keys.hmacShaKeyFor(keyBytes);
    }

    private Claims generateClaims(String subject, Map<String, ?> payload) {
        Date now = new Date();
        Date expirationAt = new Date(now.getTime() + maxAge);

        return Jwts.claims()
                .subject(subject)
                .issuedAt(now)
                .expiration(expirationAt)
                .add(payload)
                .build();
    }
}

More from this blog

클래스에 Serializable 인터페이스를 구현 받는 이유가 무엇인가요? #42

이 아티클은 깃허브 nettee-space 조직의 디스커션 #42 항목을 옮겨 온 것입니다.관련 논의: nettee-space/backend-sample-hexagonal-simple-crud/discussions/42 Question: 클래스에 Serializable 인터페이스를 구현 받는 이유가 무엇인가요? 여러 소스들을 접하면서 VO 객체 등에 Serializable를 구현받는 것을 많이 접했습니다. 저희 헥사고날(스터디 팀내 2단계 ...

Feb 7, 2025
클래스에 Serializable 인터페이스를 구현 받는 이유가 무엇인가요? #42

개념 2. JWT 액세스 토큰의 생성과 전달, Stateful한 리프레시 토큰의 생성, 전달, 보존

이전 글에서 정리에 꽤 힘을 뺐기 때문에, 이번 글에서는 서두와 부연설명을 줄이고 필요한 정보를 담아 전달해 보겠습니다. JWT 액세스 토큰 JWT 액세스 토큰은 인가에 직접 사용되는 토큰이고, stateless 하다는 장점이 있었습니다. 액세스 토큰의 생성 JWT(JSON Web Token)로 생성합니다. 비밀번호 인증 등 자격 검토 후 JWT를 발급합니다. JWT는 헤더, 페이로드, 시그니처 세 영역을 점(.) 기호로 구분한다고 했습니다....

Oct 23, 2024
개념 2. JWT 액세스 토큰의 생성과 전달, Stateful한 리프레시 토큰의 생성, 전달, 보존

Merge Simpson의 매너 있고 다정한 한국어 개발자 블로그

37 posts