[보안/SER-004] 임시비밀번호 생성 난수를 SecureRandom 으로 교체

CWE-330(취약한 난수). BizEntrprsFrtManageController.randomValue 가 임시비밀번호를
Math.random()/java.util.Random 으로 생성 → 시드 예측 가능. 암호학적 안전 난수
(SecureRandom)로 교체하고 문자 분포는 정수 범위(nextInt)로 균등 생성.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbEjijyQdS54xso1d2ks3u
This commit is contained in:
infraurp 2026-08-31 10:31:41 +09:00
parent d75c0da00e
commit e82e0611c0

View File

@ -3,7 +3,7 @@ package kr.or.arko.frt.biz.umt.web;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.security.SecureRandom;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
@ -491,56 +491,59 @@ public class BizEntrprsFrtManageController {
* @return
*/
public String randomValue(String type, int size) {
// [보안/SER-004] 임시비밀번호 생성 난수를 예측 가능한 Math.random()/java.util.Random 에서
// 암호학적 안전 난수(SecureRandom)로 교체(CWE-330). 문자 분포는 정수 범위로 균등 생성한다.
StringBuffer strPwd = new StringBuffer();
char str[] = new char[1];
// 특수기호 포함
if (type.equals("P")) {
for (int i = 0; i < size; i++) {
str[0] = (char) ((Math.random() * 94) + 33);
str[0] = (char) (SECURE_RANDOM.nextInt(94) + 33);
strPwd.append(str);
}
} else if (type.equals("A")) {
// 대문자로만
for (int i = 0; i < size; i++) {
str[0] = (char) ((Math.random() * 26) + 65);
str[0] = (char) (SECURE_RANDOM.nextInt(26) + 65);
strPwd.append(str);
}
} else if (type.equals("S")) {
// 소문자로만
for (int i = 0; i < size; i++) {
str[0] = (char) ((Math.random() * 26) + 97);
str[0] = (char) (SECURE_RANDOM.nextInt(26) + 97);
strPwd.append(str);
}
} else if (type.equals("I")) {
// 숫자형으로
int strs[] = new int[1];
for (int i = 0; i < size; i++) {
strs[0] = (int) (Math.random() * 9);
strs[0] = SECURE_RANDOM.nextInt(9);
strPwd.append(strs[0]);
}
} else if (type.equals("C")) {
// 소문자, 숫자형
Random rnd = new Random();
for (int i = 0; i < size; i++) {
if (rnd.nextBoolean()) {
strPwd.append((char) ((int) (rnd.nextInt(26)) + 97));
if (SECURE_RANDOM.nextBoolean()) {
strPwd.append((char) (SECURE_RANDOM.nextInt(26) + 97));
} else {
strPwd.append((rnd.nextInt(10)));
strPwd.append((SECURE_RANDOM.nextInt(10)));
}
}
} else if (type.equals("T")) {
// 대문자, 숫자형
Random rnd = new Random();
for (int i = 0; i < size; i++) {
if (rnd.nextBoolean()) {
strPwd.append((char) ((int) (rnd.nextInt(26)) + 65));
if (SECURE_RANDOM.nextBoolean()) {
strPwd.append((char) (SECURE_RANDOM.nextInt(26) + 65));
} else {
strPwd.append((rnd.nextInt(10)));
strPwd.append((SECURE_RANDOM.nextInt(10)));
}
}
}
return strPwd.toString();
}
/** [보안/SER-004] 임시비밀번호용 암호학적 안전 난수원(thread-safe, 공유). */
private static final SecureRandom SECURE_RANDOM = new SecureRandom();