From e82e0611c03d872da2fa413df571d51b9573c51d Mon Sep 17 00:00:00 2001 From: infraurp Date: Mon, 31 Aug 2026 10:31:41 +0900 Subject: [PATCH] =?UTF-8?q?[=EB=B3=B4=EC=95=88/SER-004]=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EB=82=9C=EC=88=98=EB=A5=BC=20SecureRandom=20?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CWE-330(취약한 난수). BizEntrprsFrtManageController.randomValue 가 임시비밀번호를 Math.random()/java.util.Random 으로 생성 → 시드 예측 가능. 암호학적 안전 난수 (SecureRandom)로 교체하고 문자 분포는 정수 범위(nextInt)로 균등 생성. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01AbEjijyQdS54xso1d2ks3u --- .../web/BizEntrprsFrtManageController.java | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/main/java/kr/or/arko/frt/biz/umt/web/BizEntrprsFrtManageController.java b/src/main/java/kr/or/arko/frt/biz/umt/web/BizEntrprsFrtManageController.java index 49d587a..3ee34b4 100644 --- a/src/main/java/kr/or/arko/frt/biz/umt/web/BizEntrprsFrtManageController.java +++ b/src/main/java/kr/or/arko/frt/biz/umt/web/BizEntrprsFrtManageController.java @@ -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();