🎲 적절하지 않은 난수 값 사용 시뮬레이터 KISA A-2 · 적절하지 않은 난수 값 사용
예측 가능한 PRNG(java.util.Random, Math.random, 현재 시간으로 시드된 LCG)로 만든 보안 토큰은 시드를 추측한 공격자가 그대로 재현할 수 있습니다. 피해자의 비밀번호 재설정 토큰이 예측되는 과정을 본 뒤 CSPRNG 방어와 비교하세요.
① 취약: 토큰 = 시간으로 시드된 LCG VULNERABLE
서버는 System.currentTimeMillis()로 시드된 선형 합동 생성기(java.util.Random 류)로 재설정 토큰을 만듭니다. 토큰에 요청 초가 노출되어 공격자는 시드를 알아내고 동일 RNG를 재현합니다.
공격자 측: 공격자는 피해자가 언제 눌렀는지 대략 압니다(토큰이 초를 노출). 같은 시드를 복원해 토큰을 그대로 재생성합니다 — 이메일 접근 불필요.
② 안전: CSPRNG에서 생성한 토큰 SECURE
CSPRNG(SecureRandom / crypto.getRandomValues)는 OS 엔트로피에서 추출하며 시드가 노출되지 않고 재현 불가능합니다. 발급 시각을 정확히 알아도 공격자 추측은 일치하지 않습니다 — 키 공간 2^128 이상.
③ 취약 vs 안전 코드
VULNERABLE
// Java — 예측 가능한 PRNG long seed = System.currentTimeMillis(); Random rng = new Random(seed); // LCG, 48비트 시드 String token = Long.toHexString(rng.nextLong()); // JS — 동일 문제 const token = Math.random().toString(36).slice(2);
SECURE
// Java — CSPRNG
SecureRandom sr = new SecureRandom(); // OS 엔트로피
byte[] b = new byte[32]; // 256-bit
sr.nextBytes(b);
String token = Base64.getUrlEncoder()
.withoutPadding().encodeToString(b);
// JS — Web Crypto
const a = new Uint8Array(32);
crypto.getRandomValues(a);
const token = [...a].map(x=>x.toString(16).padStart(2,'0')).join('');
방어 핵심: 토큰·세션ID·salt·키·OTP에 java.util.Random / Math.random / 시간 시드 LCG 사용 금지 · CSPRNG(SecureRandom, crypto.getRandomValues, /dev/urandom) 사용 · 토큰은 ≥128비트 · 시드를 노출·유도 가능하게 만들지 말 것.
⚠️ 교육용 시뮬레이션입니다. 여기의 PRNG와 'CSPRNG'는 설명용 페이지 내부 mock 생성기이며 실제 토큰이나 시스템과 무관합니다.