Vulnerability Report: GO-2025-3488
An attacker can pass a malicious malformed token which causes unexpected memory to be consumed during parsing.
무엇이 패치되었을까 보니
// Verify tests whether the provided JWT token's signature was produced by the private key
// associated with the supplied public key.
func Verify(token string, key *rsa.PublicKey) error {
parts := strings.Split(token, ".")
if len(parts) != 3 {
return errors.New("jws: invalid token received, token must have 3 parts")
}
// Verify tests whether the provided JWT token's signature was produced by the private key
// associated with the supplied public key.
func Verify(token string, key *rsa.PublicKey) error {
if strings.Count(token, ".") != 2 {
return errors.New("jws: invalid token received, token must have 3 parts")
}
parts := strings.SplitN(token, ".", 3)
이렇게 바뀌었다.
기존 코드의 문제점은
parts := strings.Split(token, ".")
if len(parts) != 3 {
return errors.New("jws: invalid token received, token must have 3 parts")
}
위 부분에서
공격자가 아래와 같은 악의적인 토큰을 전송할 수 있다
header.payload.signature...................." (수천 개의 점이 포함된 문자열)
strings.Split()은 구분자(.)를 기준으로 문자열을 모두 분할하므로 입력된 모든 점(.)에 대해 분할을 수행, 각 분할된 부분에 대해 새로운 메모리를 할당
결과적으로 수천 개의 빈 문자열을 포함하는 슬라이스가 생성이 된다.
예시 코드로 보는 메모리 소비
maliciousToken := "a" + strings.Repeat(".", 1000000)
parts := strings.Split(maliciousToken, ".") // 1,000,001개의 문자열이 메모리에 할당됨
패치를 통해서 아래와 같은 장점들이 생겼다!
- 메모리 소비가 입력 크기와 관계없이 일정하게 유지됨
- DoS(Denial of Service) 공격 가능성을 차단
- 불필요한 메모리 할당을 방지하여 전반적인 성능 향상