암호학적으로 취약한 난수 생성기(PRNG) 사용

Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)

설명

이 취약점은 보안이 필요한 상황(토큰, 세션 ID, 비밀번호 재설정 코드 등)에서 암호학적으로 안전하지 않은 난수 생성기(PRNG)를 사용하는 경우 발생합니다. 예를 들어 Go의 math/rand는 통계적 난수에는 적합하지만, 내부 알고리즘과 시드(seed)를 추측할 수 있어 공격자가 생성된 값을 예측할 수 있습니다. 공격자는 일부 난수 값을 관찰하거나 시드를 유추해 이후 생성될 토큰·코드·키를 예측하고, 세션 탈취, 계정 탈취, 인증 우회 등을 시도할 수 있습니다.

잠재적 영향

  • 예측 가능한 토큰·세션ID (토큰 및 세션 ID 예측 가능): 공격자가 난수 기반 토큰이나 세션 ID 값을 예측해 다른 사용자의 세션을 탈취하거나 인증을 우회할 수 있습니다.

  • 인증·인가 우회 (인증 및 권한 우회): 비밀번호 재설정 코드, 이메일 인증 코드 등에서 약한 난수를 사용할 경우, 공격자가 무차별 대입이나 패턴 분석으로 코드를 맞춰 계정을 탈취할 수 있습니다.

  • 암호 키 약화 (암호 키 보안 약화): 암호 키, IV, nonce 등 암호 파라미터를 취약한 PRNG로 생성하면 암호화 자체의 안전성이 크게 떨어져, 암호문 복호화나 위조가 가능해질 수 있습니다.

해결 방법

  • 보안 용도에는 반드시 crypto/rand 사용: 토큰, 세션 ID, 인증 코드, 암호 키, IV, nonce 등 보안 관련 난수는 모두 crypto/rand로 생성합니다.

  • math/rand 사용 범위 제한: 게임 로직, 샘플링, 로드 밸런싱 같은 비보안(non-security) 용도에만 math/rand를 사용합니다.

  • 난수 길이 충분히 확보: 토큰·코드를 만들 때는 최소 128bit(16byte) 이상 난수를 사용해 무차별 대입 공격을 어렵게 만듭니다.

  • 공통 유틸 함수 작성: 팀 차원에서 GenerateSecureToken 등 공용 secure-random 헬퍼 함수를 만들고, 모든 서비스에서 이것만 사용하도록 가이드합니다.

  • 코드 리뷰 체크 리스트에 포함: PRNG 사용 시 crypto/rand인지, 보안 목적에 적절한 길이와 인코딩(예: hex, base64)을 사용하는지 확인합니다.

취약한 코드 및 안전한 코드 예시

취약한 코드

안전한 코드

설명:

  • 취약한 코드: 위 비준수 코드에서는 비밀번호 재설정 토큰을 생성하는 데 math/rand를 사용합니다. math/rand는 시드를 알거나 추측할 수 있으면 생성되는 난수 순서를 모두 예측할 수 있는 비암호학적 PRNG입니다. 시드로 현재 시간(time.Now().UnixNano())을 사용하기 때문에, 공격자는 요청 시간을 대략적으로 알고 있다면 같은 시드로 토큰을 재현하거나 주변 값을 시도해 실제 토큰을 맞출 수 있습니다. 따라서 토큰, 세션 ID 같은 보안 민감 값에 math/rand를 사용하는 것은 취약합니다.

  • 안전한 코드: 준수 코드에서는 Go의 crypto/rand 패키지의 rand.Read를 사용해 암호학적으로 안전한 난수를 생성합니다. 이 난수는 운영체제의 CSPRNG(cryptographically secure PRNG)를 기반으로 하며, 외부에서 시드나 내부 상태를 현실적으로 예측할 수 없습니다. 또한 충분한 길이(128비트)를 사용하여 무차별 대입 공격을 어렵게 만들고, hex.EncodeToString으로 안전하게 문자열로 변환해 토큰으로 사용합니다. 이로 인해 공격자가 토큰 값을 예측하거나 재현하기 매우 어려워져 취약점이 완화됩니다.

참조

Last updated