🏛️ 홍익인간CMS 개발자 매뉴얼

Version 202506 | Updated 2025-06-12
🌐 언어 선택: 🇰🇷 한국어 🇲🇳 Монгол 🇺🇸 English

7. 🔒 보안 가이드

7.1 보안 개요

홍익인간CMS는 다양한 보안 위협으로부터 시스템을 보호하기 위한 여러 보안 기능을 제공합니다. 이 장에서는 홍익인간CMS의 현재 구현된 보안 기능과 추가로 지원 가능한 기능, 그리고 개발 시 준수해야 할 보안 가이드라인을 설명합니다.

7.1.1 보안 아키텍처

홍익인간CMS의 보안 아키텍처는 다음과 같은 계층으로 구성되어 있습니다:

현재 구현된 보안 기능

  • HTTP 보안 헤더 설정
  • XSS 방지 필터
  • 기본 암호화/복호화 (AES, SHA-256)
  • 개인정보 접근 이력 관리
  • 세션 관리
  • 입력값 검증 유틸리티 (HumanValidatorUtil)

🔧지원 가능한 보안 기능

  • Spring Security 기반 인증
  • 역할 기반 접근 제어(RBAC)
  • CSRF 방지
  • 고급 암호화 기법(BCrypt, PBKDF2)
  • Bean Validation을 통한 입력값 검증

🛡️보안 영역

  • 인증 및 권한 관리
  • 데이터 보안
  • 애플리케이션 보안
  • 로깅 및 감사

7.2 현재 구현된 보안 기능

7.2.1 XSS(Cross-Site Scripting) 방지

홍익인간CMS는 XSS 공격을 방지하기 위한 필터를 제공합니다. 이 필터는 사용자 입력값에서 악성 스크립트를 제거하여 XSS 공격을 방지합니다.

주요 기능

XSS 방지 필터 구현

XSSWebFilter.java - 실제 구현된 코드

public class XSSWebFilter implements Filter {
    // ...
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // ...
        if (isRequestCheck) {
            // 파라미터에 특수문자 포함 시 제거
            chain.doFilter(new HTMLTagFilterRequestWrapper(req), response);
        } else {
            chain.doFilter(request, response);
        }
        // ...
    }
}
web.xml 설정

실제 구현된 XSS 필터 설정

<filter>
    <filter-name>XSSWebFilter</filter-name>
    <filter-class>humanframe.web.filter.XSSWebFilter</filter-class>
    <async-supported>true</async-supported>
</filter>
<filter-mapping>
    <filter-name>XSSWebFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

7.2.2 암호화/복호화

홍익인간CMS는 기본적인 암호화/복호화 기능을 제공합니다. 이 기능은 개인정보 및 비밀번호 등 민감한 정보를 보호하는 데 사용됩니다.

주요 기능

암호화 구현

HumanCryptoServiceImpl.java - 실제 구현된 코드

@Service("humanCryptoService")
public class HumanCryptoServiceImpl extends HumanAbstractServiceImpl implements HumanCryptoService {

    @Resource(name="propertiesService")
    private EgovPropertyService properties;

    @Resource(name="ARIACryptoService")
    private EgovCryptoService cryptoService;

    @Resource(name="passwordEncoder")
    public EgovPasswordEncoder egovPasswordEncoder;

    @Override
    public String encrypt(String str) throws Exception {
        byte[] encrypted = cryptoService.encrypt(str.getBytes("UTF-8"), properties.getString("CRYPTO_KEY"));
        String encryptStr = new String(Base64.encodeBase64(encrypted));
        return encryptStr;
    }

    @Override
    public String decrypt(String str) throws Exception {
        byte[] decrypted = cryptoService.decrypt(Base64.decodeBase64(str.getBytes()), properties.getString("CRYPTO_KEY"));
        return new String(decrypted, "UTF-8");
    }

    /**
     * 비밀번호를 암호화하는 기능(복호화가 되면 안되므로 SHA-256 인코딩 방식 적용)
     */
    @Override
    public String encryptPassword(String password, String id) throws Exception {
        if (password == null) {
            return "";
        }

        byte[] hashValue = null; // 해쉬값
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        md.reset();
        md.update(id.getBytes());
        hashValue = md.digest(password.getBytes());

        return new String(Base64.encodeBase64(hashValue));
    }
}

7.2.3 개인정보 접근 이력 관리

홍익인간CMS는 개인정보 접근 이력을 관리하는 기능을 제공합니다. 이 기능은 개인정보보호법 준수를 위해 중요합니다.

주요 기능

개인정보 접근 이력 관리 구현

AdminPrivacyAspect.java - 실제 구현된 코드

@Aspect
@Order(2)
@Component
public class AdminPrivacyAspect {

    @Resource(name = "mngPrivacyService")
    private MngPrivacyService mngPrivacyService;

   // 관리자 권한 체크
   @Pointcut("execution(* humanframe.backoffice..Admin*Controller.form(..))"
           + "|| execution(* humanframe.backoffice..Admin*Controller.list(..))"
           + "|| execution(* humanframe.backoffice..Admin*Controller.view(..))"
           + "|| execution(* humanframe.backoffice..Admin*Controller.action(..))"
           + "|| execution(* humanframe.web.controller.admin..Admin*Controller.list(..))"
           + "|| execution(* humanframe.web.controller.admin..Admin*Controller.view(..))"
           + "|| execution(* humanframe.web.controller.admin..Admin*Controller.form(..))"
           + "|| execution(* humanframe.web.controller.admin..Admin*Controller.action(..))")
    private void checkAdminPrivacy() {}

    @Before(value = "checkAdminPrivacy()")
    private void beforeCheckAdminPrivacy(JoinPoint joinPoint) throws Exception {
        HttpServletRequest request = null;
        for (Object o : joinPoint.getArgs()) {
            if (o instanceof HttpServletRequest)
                request = (HttpServletRequest)o;
        }

        if(request != null) {
            // 개인정보 접근이력 저장
            String logTxt = "IP:" + request.getRemoteAddr() + ", " + className + "." + methodName;
            for(MngMenuVO sessMenuVO : mngrSession.getMngMenuList()){
                if(sessMenuVO.getMenuUrl().contains(request.getServletPath().substring(0,request.getServletPath().lastIndexOf("/")))){
                    if(sessMenuVO.getPrivacyAt().equals("Y")) {
                        mngPrivacyService.createMngPriacyAccess(logTy, request.getServletPath(), logTxt);
                    }
                }
            }
        }
    }
}

7.2.4 HTTP 보안 헤더 설정

홍익인간CMS는 HTTP 보안 헤더를 통해 기본적인 웹 보안을 강화합니다.

주요 기능

web.xml 설정

실제 구현된 HTTP 보안 설정

<session-config>
    <session-timeout>60</session-timeout>
    <cookie-config>
        <http-only>true</http-only> <!-- 서버 요청이 있을 때에만 쿠키가 전송되도록 설정 -->
        <!-- <secure>true</secure> --> <!-- SSL 통신 채널 연결 시에만 쿠키를 전송 하도록 설정 -->
    </cookie-config>    
    <tracking-mode>COOKIE</tracking-mode>        
</session-config>

<security-constraint>
    <display-name></display-name>
    <web-resource-collection>
        <web-resource-name>restricted methods</web-resource-name>
        <url-pattern>/*</url-pattern>
        <http-method>TRACE</http-method>
        <http-method>DELETE</http-method>
        <http-method>PUT</http-method>
        <http-method>HEAD</http-method>
        <http-method>OPTIONS</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>nobody</role-name>
    </auth-constraint>
</security-constraint>

7.2.5 입력값 검증 유틸리티

홍익인간CMS는 humanframe.core 라이브러리를 통해 다양한 입력값 검증 유틸리티를 제공합니다.

주요 기능

입력값 검증 구현

HumanValidatorUtil.java - 실제 코드 일부

public class HumanValidatorUtil {

    // 정규식 패턴
    final static private String pattern_alpha = "^[A-Za-z]*$";
    final static private String pattern_numeric = "^[0-9]*$";
    final static private String pattern_korean = "^[ㄱ-ㅎ|가-힣]*$";
    final static private String pattern_email = "^[-A-Za-z0-9_]+[-A-Za-z0-9_.]*[@]{1}[-A-Za-z0-9_]+[-A-Za-z0-9_.]*[.]{1}[A-Za-z]{2,5}$";
    final static private String pattern_url = "^(https?)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]";
    final static private String pattern_invalid_password = "^(?=.*?[a-zA-Z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,25}$";
    
    // 이메일 검증
    public static boolean isEmail(String value) {
        return nullChecker(5, value);
    }
    
    // URL 검증
    public static boolean isUrl(String value) {
        return nullChecker(6, value);
    }
    
    // 비밀번호 복잡성 검증
    public static boolean isValidPassword(String value){
        return nullChecker(10, value);
    }
    
    // 알파벳+숫자 조합 검증
    public static boolean isAlphaNumeric(String value) {
        if (!nullChecker(value)) {
            boolean bReturn = true;
            char[] cArr = value.toCharArray();
            int alphaLen = 0;
            int numericLen = 0;
            for (char c : cArr) {
                if (isAlpha(String.valueOf(c))) {
                    alphaLen++;
                }
                if (isNumeric(String.valueOf(c))) {
                    numericLen++;
                }
            }

            if ((alphaLen == 0) || (numericLen == 0) || (cArr.length != (alphaLen + numericLen))){
                bReturn = false;
            }

            return bReturn;
        } else {
            return false;
        }
    }
}

7.3 보안 코딩 규칙

홍익인간CMS 개발 시 준수해야 할 보안 코딩 규칙은 다음과 같습니다.

7.3.1 오류 메시지 출력 정보 노출 방지

오류 메시지에 민감한 정보가 노출되지 않도록 주의해야 합니다.

잘못된 예시

try {
    // 데이터베이스 작업
} catch (SQLException e) {
    e.printStackTrace(); // 오류 스택 트레이스 노출
    return "데이터베이스 오류: " + e.getMessage(); // 오류 메시지 노출
}

올바른 예시

try {
    // 데이터베이스 작업
} catch (SQLException e) {
    logger.error("데이터베이스 오류", e); // 로그에만 기록
    return "시스템 오류가 발생했습니다. 관리자에게 문의하세요."; // 일반적인 오류 메시지
}

7.3.2 오류 상황 대응 부재 방지

모든 예외 상황에 대한 적절한 처리가 필요합니다.

잘못된 예시

public void processData(String data) {
    // 예외 처리 없음
    int value = Integer.parseInt(data); // NumberFormatException 발생 가능
    // 처리 로직
}

올바른 예시

public void processData(String data) {
    try {
        int value = Integer.parseInt(data);
        // 처리 로직
    } catch (NumberFormatException e) {
        logger.error("숫자 변환 오류", e);
        throw new BusinessException("유효하지 않은 데이터입니다.");
    }
}

7.3.3 적절하지 않은 예외 처리 방지

예외를 무시하거나 부적절하게 처리하지 않도록 주의해야 합니다.

잘못된 예시

try {
    // 파일 작업
} catch (Exception e) {
    // 아무 처리 없음 (예외 무시)
}

올바른 예시

try {
    // 파일 작업
} catch (IOException e) {
    logger.error("파일 처리 오류", e);
    throw new BusinessException("파일 처리 중 오류가 발생했습니다.");
}

7.3.4 구체적인 예외 처리

예외 처리 시 일반적인 Exception 클래스보다 구체적인 예외 클래스를 사용해야 합니다.

잘못된 예시

try {
    // 파일 읽기, 네트워크 요청, 데이터베이스 쿼리 등 다양한 작업
} catch (Exception e) {
    logger.error("오류 발생", e);
    throw new RuntimeException("처리 중 오류가 발생했습니다.");
}

올바른 예시

try {
    // 파일 읽기 작업
} catch (FileNotFoundException e) {
    logger.error("파일을 찾을 수 없음", e);
    throw new BusinessException("요청하신 파일을 찾을 수 없습니다.");
} catch (IOException e) {
    logger.error("파일 읽기 오류", e);
    throw new BusinessException("파일 읽기 중 오류가 발생했습니다.");
} catch (SQLException e) {
    logger.error("데이터베이스 오류", e);
    throw new SystemException("데이터베이스 처리 중 오류가 발생했습니다.");
} catch (RuntimeException e) {
    logger.error("런타임 오류", e);
    throw new SystemException("시스템 처리 중 오류가 발생했습니다.");
}
💡

구체적인 예외 처리의 장점

  • 명확한 오류 원인 파악: 구체적인 예외 클래스를 사용하면 오류의 원인을 더 명확하게 파악할 수 있습니다.
  • 적절한 대응 가능: 예외 유형에 따라 적절한 대응 방법을 선택할 수 있습니다.
  • 코드 가독성 향상: 어떤 예외가 발생할 수 있는지 명확하게 표현되어 코드의 가독성이 향상됩니다.
  • 유지보수성 향상: 특정 예외 처리 로직을 수정할 때 다른 예외 처리에 영향을 주지 않습니다.
  • 보안 강화: 예외 유형에 따라 적절한 오류 메시지를 제공하여 민감한 정보 노출을 방지할 수 있습니다.

7.3.5 SQL 인젝션 방지

SQL 인젝션 공격을 방지하기 위한 코딩 규칙을 준수해야 합니다. 홍익인간CMS는 MyBatis를 사용하여 SQL 쿼리를 관리하므로, 파라미터 바인딩을 통해 SQL 인젝션을 방지할 수 있습니다.

잘못된 예시

직접 문자열 연결을 통한 SQL 생성 (사용하지 말 것)
public BbsVO selectBbsVulnerable(String bbsNo) {
    String sqlId = "bbs.selectBbs";
    String dynamicSql = sqlId + "_" + bbsNo; // 위험: 사용자 입력이 SQL ID에 직접 포함됨
    return (BbsVO) selectOne(dynamicSql);
}

올바른 예시 (MyBatis 매핑 활용)

DAO 클래스 내 메소드
public BbsVO selectBbs(int bbsNo) {
    Map<String, Object> paramMap = new HashMap<String, Object>();
    paramMap.put("bbsNo", bbsNo);
    return (BbsVO) selectOne("bbs.selectBbs", paramMap);
}
MyBatis XML 매핑 파일
<select id="bbs.selectBbs" parameterType="java.util.Map" resultType="humanframe.web.vo.BbsVO">
    SELECT 
        bbs_no,
        title,
        content,
        reg_dt
    FROM 
        tn_bbs 
    WHERE 
        bbs_no = #{bbsNo}
</select>

7.3.6 코딩 컨벤션 준수

일관된 코딩 스타일을 유지하기 위해 코딩 컨벤션을 준수해야 합니다.

📝주요 규칙

  • 클래스, 메소드, 변수 등의 명명 규칙 준수
  • 들여쓰기 및 공백 사용 규칙 준수
  • 주석 작성 규칙 준수
  • 패키지 구조 규칙 준수

7.4 보안 취약점 점검 및 관리

7.4.1 보안 취약점 점검 항목

다음과 같은 보안 취약점 점검 항목을 주기적으로 확인하는 것이 좋습니다:

🔐 인증 및 권한 관리

  • 인증 우회 취약점
  • 권한 검증 누락
  • 세션 관리 취약점

✅ 입력값 검증

  • XSS 취약점
  • SQL 인젝션 취약점
  • 명령어 인젝션 취약점

📤 출력값 처리

  • 민감 정보 노출
  • 오류 메시지 노출

📁 파일 처리

  • 경로 조작 취약점
  • 파일 업로드 취약점

🔒 암호화

  • 취약한 암호화 알고리즘 사용
  • 암호화 키 관리 취약점

7.4.2 보안 패치 및 업데이트

홍익인간CMS의 보안을 유지하기 위해 정기적인 보안 패치 및 업데이트가 필요합니다.

패치 적용 절차

🔍 보안 취약점 확인

시스템에 영향을 줄 수 있는 보안 취약점 확인

📋 패치 내용 검토

패치의 내용과 영향 범위 검토

🧪 테스트 환경 적용

테스트 환경에서 패치 적용 및 테스트

🚀 운영 환경 적용

운영 환경에 패치 적용

📊 결과 모니터링

패치 적용 결과 모니터링

의존성 라이브러리 관리

📋 라이브러리 목록 관리

의존성 라이브러리 목록 관리

🔍 취약점 정보 모니터링

보안 취약점 정보 모니터링

🔄 라이브러리 업데이트

취약점이 발견된 라이브러리 업데이트

🧪 호환성 테스트

업데이트 후 호환성 테스트

7.5 결론

홍익인간CMS는 기본적인 보안 기능을 제공하며, 개발자는 필요에 따라 추가적인 보안 기능을 구현할 수 있습니다. 현재 구현된 기능으로는 XSS 방지 필터, 암호화/복호화, 개인정보 접근 이력 관리, HTTP 보안 헤더 설정, 입력값 검증 유틸리티 등이 있으며, 이를 통해 기본적인 보안 요구사항을 충족할 수 있습니다.

추가적인 보안 강화가 필요한 경우, Spring Security 기반 인증, 역할 기반 접근 제어, CSRF 방지, 고급 암호화 기법 등을 구현할 수 있습니다. 이러한 기능들은 humanframe.core 라이브러리를 확장하여 구현하거나, 외부 라이브러리를 활용하여 구현할 수 있습니다.

⚠️

중요사항

보안은 지속적인 관리와 개선이 필요한 영역이므로, 정기적인 보안 점검과 업데이트를 통해 시스템의 안전성을 유지하는 것이 중요합니다. 개발자는 이 매뉴얼에서 제시하는 보안 코딩 규칙을 준수하고, 필요에 따라 추가적인 보안 기능을 구현하여 홍익인간CMS의 보안을 강화할 수 있습니다.