불충분한 난수 사용

Insecure Randomness

설명

보안 민감 값(비밀번호, reset 토큰, session ID, OTP, CSRF token 등)을 Math.random() 같은 비암호학적 PRNG로 생성하면 출력이 예측 가능해집니다. 이런 PRNG는 내부 상태가 작은 편이고 통계적으로 추정이 가능하여, 충분한 엔트로피(무작위성)를 제공하지 못합니다. 공격자는 짧은 토큰 공간을 무차별 대입(brute force)하거나, 동일 프로세스에서 얻은 여러 출력값을 바탕으로 다음 값을 추정해 토큰/세션을 맞출 수 있습니다.

잠재적 영향

  • 인증/세션 탈취: 예측 가능한 token 또는 session ID를 추측해 타인의 계정으로 로그인하거나 세션을 가로챌 수 있습니다.

  • 비밀번호 재설정 하이재킹: reset 토큰을 맞춰 비밀번호를 변경, 계정을 탈취할 수 있습니다.

  • 2FA/OTP 우회: 예측 가능한 OTP/코드를 생성할 경우, 추가 인증을 무력화할 수 있습니다.

  • CSRF 방어 우회: CSRF token이 예측 가능하면 위조 요청을 방어하지 못합니다.

  • 암호화 안전성 약화(Nonce/IV 예측): 예측 가능한 nonce/키로 인해 암호화 보장이 약화되고 메시지 변조/위조 위험이 커집니다.

해결 방법

  • CSPRNG 사용: 보안 민감 값 생성에는 반드시 암호학적 난수 생성기(CSPRNG)를 사용하세요.

    • Browser: window.crypto.getRandomValues

    • Node.js: crypto.randomBytes, (숫자 코드가 필요하면) crypto.randomInt

  • 충분한 길이 확보: 토큰/키는 최소 128비트(권장 192~256비트) 이상으로 생성하세요.

  • 안전한 인코딩: hex 또는 base64url로 인코딩하세요. 임의 문자셋으로 매핑할 때는 나머지(%) 연산으로 인한 bias가 생기지 않도록 rejection sampling 등을 사용하세요.

  • Math.random 금지: 보안 목적(비밀번호/토큰/키/nonce/OTP 등)에는 Math.random을 절대 사용하지 마세요.

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

취약한 코드

안전한 코드

설명:

  • 취약한 코드: Math.random()은 비암호학적 PRNG로, 출력이 통계적으로 예측 가능하여 토큰/세션/OTP 등 보안 민감 값에 적합하지 않습니다. base36 문자열로 변환하는 과정에서도 실제 엔트로피가 더 줄어들어 brute force로 충분히 맞출 수 있는 위험이 커집니다.

  • 안전한 코드: CSPRNG(crypto.randomBytes, crypto.getRandomValues)는 공격자가 실질적으로 예측할 수 없는 강한 무작위성을 제공합니다. 256비트 길이와 hex/base64url 인코딩을 사용해 편향 없이 충분한 엔트로피를 확보하며, 토큰 추측 및 세션/계정 탈취 가능성을 효과적으로 차단합니다.

참조

Last updated