보안취약점 조치
@a526ad07e126b30d81fbef0ab57109e577ccd426
--- pom.xml
+++ pom.xml
... | ... | @@ -24,7 +24,7 @@ |
| 24 | 24 |
<repositories> |
| 25 | 25 |
<repository> |
| 26 | 26 |
<id>mvn2</id> |
| 27 |
- <url>http://repo1.maven.org/maven2/</url> |
|
| 27 |
+ <url>https://repo1.maven.org/maven2/</url> |
|
| 28 | 28 |
<releases> |
| 29 | 29 |
<enabled>true</enabled> |
| 30 | 30 |
</releases> |
... | ... | @@ -34,7 +34,7 @@ |
| 34 | 34 |
</repository> |
| 35 | 35 |
<repository> |
| 36 | 36 |
<id>egovframe</id> |
| 37 |
- <url>http://www.egovframe.go.kr/maven/</url> |
|
| 37 |
+ <url>https://maven.egovframe.go.kr/maven/</url> |
|
| 38 | 38 |
<releases> |
| 39 | 39 |
<enabled>true</enabled> |
| 40 | 40 |
</releases> |
+++ src/main/java/egovframework/com/cmm/InterceptorHandler.java
... | ... | @@ -0,0 +1,101 @@ |
| 1 | +package egovframework.com.cmm; | |
| 2 | + | |
| 3 | +import java.util.Enumeration; | |
| 4 | +import java.util.regex.Pattern; | |
| 5 | + | |
| 6 | +import javax.servlet.http.HttpServletRequest; | |
| 7 | +import javax.servlet.http.HttpServletResponse; | |
| 8 | + | |
| 9 | +import org.springframework.web.servlet.ModelAndView; | |
| 10 | +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; | |
| 11 | + | |
| 12 | +import egovframework.com.cmm.util.EgovXSSUtil; | |
| 13 | + | |
| 14 | + | |
| 15 | +public class InterceptorHandler extends HandlerInterceptorAdapter{ | |
| 16 | + | |
| 17 | + private static final Pattern SQL_PATTERN = Pattern.compile( | |
| 18 | + "(?i)(select|insert|delete|update|create|drop|alter|where|substr|substring|group by|union|xp_cmdshell|and|or|having|from|unio|case|when|if|--|;|/\\*|\\*/|\\bor\\b|\\band\\b)" | |
| 19 | + ); | |
| 20 | + | |
| 21 | + @Override | |
| 22 | + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { | |
| 23 | + | |
| 24 | + /** | |
| 25 | + * URL 호출 전 넘어오는 파라미터 체크 | |
| 26 | + * request로 넘어오는 모든 파라미터 데이터를 검사하여 XSS 문자가 포함되어 있으면 메인화면으로 튕김 | |
| 27 | + * */ | |
| 28 | + boolean returnSts1 = true; | |
| 29 | + Enumeration e = request.getParameterNames(); | |
| 30 | + while ( e.hasMoreElements() ){ | |
| 31 | + String name = (String) e.nextElement(); | |
| 32 | + | |
| 33 | + { //XSS 보안조치 | |
| 34 | + if(name.toLowerCase().contains("cmplntreqcn") | |
| 35 | + || name.toLowerCase().contains("autcn") | |
| 36 | + || name.toLowerCase().contains("file_0") | |
| 37 | + || name.toLowerCase().contains("file_1") | |
| 38 | + || name.toLowerCase().contains("seccn") | |
| 39 | + || name.toLowerCase().contains("nttcn") | |
| 40 | + ) { | |
| 41 | + String[] values = request.getParameterValues(name); | |
| 42 | + for (String value : values) { | |
| 43 | + | |
| 44 | + boolean returnSts = EgovXSSUtil.cleanXSS(value); | |
| 45 | + if(!returnSts) {//XSS 문자 체크 결과 false일 경우 메인화면으로 이동 | |
| 46 | + returnSts1 = returnSts; | |
| 47 | + System.out.println("+++++++++++++++++++++++++++XSS 필터 처리 Filter::: "); | |
| 48 | + System.out.println("name="+ name + ", value="+ value); | |
| 49 | + System.out.println("+++++++++++++++++++++++++++XSS 필터 처리 Filter End::: "); | |
| 50 | + response.sendRedirect(request.getContextPath() + "/"); | |
| 51 | + } | |
| 52 | + } | |
| 53 | + } | |
| 54 | + } | |
| 55 | + | |
| 56 | + { //SQL Injection 보안조치 | |
| 57 | + if(name.toLowerCase().contains("searchsortcnd") | |
| 58 | + || name.toLowerCase().contains("searchsortord") | |
| 59 | + ) { | |
| 60 | + | |
| 61 | + //파라미터 중에 URL 주소를 넘겨주는 부분이 있어서 해당 부분에것 select~, update~, delete~ 로 시작하는 주소경로가 있어서 제외처리를 하였음 | |
| 62 | + String[] values = request.getParameterValues(name); | |
| 63 | + | |
| 64 | + for (String value : values) { | |
| 65 | + if (value != null && SQL_PATTERN.matcher(value.toLowerCase()).find()) { | |
| 66 | + System.out.println("+++++++++++++++++++++++++++XSS Html 필터 처리 Filter Start::: "); | |
| 67 | + System.out.println("name="+ name + ", value="+ value); | |
| 68 | + System.out.println("+++++++++++++++++++++++++++XSS Html 필터 처리 Filter End::: "); | |
| 69 | + response.sendRedirect(request.getContextPath() + "/"); | |
| 70 | + } | |
| 71 | + } | |
| 72 | + } | |
| 73 | + } | |
| 74 | + } | |
| 75 | + | |
| 76 | + if(!returnSts1) {//XSS 포함문자가 있는경우 메인화면으로 이동시킨다. | |
| 77 | + response.sendRedirect(request.getContextPath() + "/"); | |
| 78 | + return true; | |
| 79 | + } | |
| 80 | + | |
| 81 | + return true; | |
| 82 | + } | |
| 83 | + | |
| 84 | + /* | |
| 85 | + * view 화면으로 데이터가 넘어가기 이전에 실행 | |
| 86 | + * modelAndView 값을 체크할 수 있음 | |
| 87 | + * */ | |
| 88 | + @Override | |
| 89 | + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { | |
| 90 | + super.postHandle(request, response, handler, modelAndView); | |
| 91 | + } | |
| 92 | + | |
| 93 | + /* | |
| 94 | + * | |
| 95 | + * view에서 모든 처리를 완료한 후에 실행 | |
| 96 | + * */ | |
| 97 | + @Override | |
| 98 | + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { | |
| 99 | + super.afterCompletion(request, response, handler, ex); | |
| 100 | + } | |
| 101 | +} |
--- src/main/java/egovframework/com/cmm/util/EgovXSSUtil.java
+++ src/main/java/egovframework/com/cmm/util/EgovXSSUtil.java
... | ... | @@ -2,6 +2,71 @@ |
| 2 | 2 |
|
| 3 | 3 |
public class EgovXSSUtil {
|
| 4 | 4 |
|
| 5 |
+ public static boolean cleanXSS(String str) {
|
|
| 6 |
+ |
|
| 7 |
+ String str_low= str.toLowerCase(); |
|
| 8 |
+ boolean returnSts = true; |
|
| 9 |
+ if( |
|
| 10 |
+ str_low.contains("javascript")
|
|
| 11 |
+ ||str_low.contains("eval")
|
|
| 12 |
+ ||str_low.contains("title")
|
|
| 13 |
+ ||str_low.contains("onload")
|
|
| 14 |
+ ||str_low.contains("onmousewheel")
|
|
| 15 |
+ ||str_low.contains("onactive")
|
|
| 16 |
+ ||str_low.contains("expression")
|
|
| 17 |
+ ||str_low.contains("charset")
|
|
| 18 |
+ ||str_low.contains("ondataavailable")
|
|
| 19 |
+ ||str_low.contains("oncut")
|
|
| 20 |
+ ||str_low.contains("applet")
|
|
| 21 |
+ ||str_low.contains("document")
|
|
| 22 |
+ ||str_low.contains("onafteripudate")
|
|
| 23 |
+ ||str_low.contains("onclick")
|
|
| 24 |
+ ||str_low.contains("meta")
|
|
| 25 |
+ ||str_low.contains("string")
|
|
| 26 |
+ ||str_low.contains("onmousedown")
|
|
| 27 |
+ ||str_low.contains("onchange")
|
|
| 28 |
+ ||str_low.contains("xml")
|
|
| 29 |
+ ||str_low.contains("create")
|
|
| 30 |
+ ||str_low.contains("onbeforeactivate")
|
|
| 31 |
+ ||str_low.contains("onbeforecut")
|
|
| 32 |
+ ||str_low.contains("blink")
|
|
| 33 |
+ ||str_low.contains("append")
|
|
| 34 |
+ ||str_low.contains("onbeforecopy")
|
|
| 35 |
+ ||str_low.contains("ondbclick")
|
|
| 36 |
+ ||str_low.contains("link")
|
|
| 37 |
+ ||str_low.contains("binding")
|
|
| 38 |
+ ||str_low.contains("onbeforedeactivate")
|
|
| 39 |
+ ||str_low.contains("ondeactivate")
|
|
| 40 |
+ ||str_low.contains("style")
|
|
| 41 |
+ ||str_low.contains("alert")
|
|
| 42 |
+ ||str_low.contains("prompt")
|
|
| 43 |
+ ||str_low.contains("comfire")
|
|
| 44 |
+ ||str_low.contains("ondrag")
|
|
| 45 |
+ ||str_low.contains("script")
|
|
| 46 |
+ ||str_low.contains("msgbox")
|
|
| 47 |
+ ||str_low.contains("cnbeforeprint")
|
|
| 48 |
+ ||str_low.contains("embed")
|
|
| 49 |
+ ||str_low.contains("refresh")
|
|
| 50 |
+ ||str_low.contains("cnbeforepaste")
|
|
| 51 |
+ ||str_low.contains("object")
|
|
| 52 |
+ ||str_low.contains("void")
|
|
| 53 |
+ ||str_low.contains("iframe")
|
|
| 54 |
+ ||str_low.contains("cookie")
|
|
| 55 |
+ ||str_low.contains("ondatasetchaged")
|
|
| 56 |
+ ||str_low.contains("ondragend")
|
|
| 57 |
+ ||str_low.contains("ondragenter")
|
|
| 58 |
+ ||str_low.contains("ondragleave")
|
|
| 59 |
+ ||str_low.contains("onbeforeeditfocus")
|
|
| 60 |
+ ||str_low.contains("onbeforeuload")
|
|
| 61 |
+ ||str_low.contains("ondragover")
|
|
| 62 |
+ ||str_low.contains("onerror")
|
|
| 63 |
+ ) |
|
| 64 |
+ {
|
|
| 65 |
+ returnSts = false; |
|
| 66 |
+ } |
|
| 67 |
+ return returnSts; |
|
| 68 |
+ } |
|
| 69 |
+ |
|
| 5 | 70 |
public String unscript(String data) {
|
| 6 | 71 |
if (data == null || data.trim().equals("")) {
|
| 7 | 72 |
return ""; |
+++ src/main/java/egovframework/com/cmm/util/FileExtCheckUtil.java
... | ... | @@ -0,0 +1,18 @@ |
| 1 | +package egovframework.com.cmm.util; | |
| 2 | + | |
| 3 | +public class FileExtCheckUtil { | |
| 4 | + | |
| 5 | + public static boolean fileExtCheck(String fileExt) { | |
| 6 | + final String[] PERMISSION_FILE_EXT_ARR = {"ZIP", "GIF", "JPEG", "JPG", "PNG", "BMP", "PDF", "HWP", "XLSX", "DOCX", "PPTX"}; | |
| 7 | + boolean isPermissionFileExt = false; | |
| 8 | + fileExt = fileExt.toUpperCase(); | |
| 9 | + for( int i = 0; i < PERMISSION_FILE_EXT_ARR.length; i++ ) { | |
| 10 | + System.out.println(fileExt + " : "+PERMISSION_FILE_EXT_ARR[i]); | |
| 11 | + if( PERMISSION_FILE_EXT_ARR[i].equals(fileExt) ) { | |
| 12 | + isPermissionFileExt = true; | |
| 13 | + break; | |
| 14 | + } | |
| 15 | + } | |
| 16 | + return isPermissionFileExt; | |
| 17 | + } | |
| 18 | +} |
--- src/main/java/egovframework/let/itsm/edu/web/EduManageController.java
+++ src/main/java/egovframework/let/itsm/edu/web/EduManageController.java
... | ... | @@ -24,6 +24,8 @@ |
| 24 | 24 |
import egovframework.com.cmm.service.EgovFileMngService; |
| 25 | 25 |
import egovframework.com.cmm.service.EgovFileMngUtil; |
| 26 | 26 |
import egovframework.com.cmm.service.FileVO; |
| 27 |
+import egovframework.com.cmm.util.FileExtCheckUtil; |
|
| 28 |
+import egovframework.com.cmm.util.RedirectUrlMaker; |
|
| 27 | 29 |
import egovframework.let.cop.bbs.service.BoardVO; |
| 28 | 30 |
import egovframework.let.itsm.audit.service.AuditItemVO; |
| 29 | 31 |
import egovframework.let.itsm.audit.service.AuditVO; |
... | ... | @@ -772,7 +774,6 @@ |
| 772 | 774 |
final MultipartHttpServletRequest multiRequest, |
| 773 | 775 |
ModelMap model) throws Exception {
|
| 774 | 776 |
|
| 775 |
- |
|
| 776 | 777 |
ModelAndView modelAndView = new ModelAndView(); |
| 777 | 778 |
modelAndView.setViewName("jsonView");
|
| 778 | 779 |
Boolean isAuthenticated = EgovUserDetailsHelper.isAuthenticated(); |
... | ... | @@ -789,6 +790,13 @@ |
| 789 | 790 |
result = fileUtil.parseFileInf(files, "AUDIT_", 0, "", "", ""); |
| 790 | 791 |
if(result.size() != 0) {
|
| 791 | 792 |
for(FileVO tempFile : result) {
|
| 793 |
+ String extension = tempFile.orignlFileNm.substring(tempFile.orignlFileNm.lastIndexOf(".")+1);
|
|
| 794 |
+ |
|
| 795 |
+ if(!FileExtCheckUtil.fileExtCheck(extension)) {
|
|
| 796 |
+ modelAndView.addObject("result", "extension");
|
|
| 797 |
+ return modelAndView; |
|
| 798 |
+ } |
|
| 799 |
+ |
|
| 792 | 800 |
tempFile.setRefId(eduVO.getAutId()); |
| 793 | 801 |
} |
| 794 | 802 |
} |
--- src/main/java/egovframework/let/uss/umt/web/EgovUserManageController.java
+++ src/main/java/egovframework/let/uss/umt/web/EgovUserManageController.java
... | ... | @@ -314,8 +314,22 @@ |
| 314 | 314 |
return "uat/uia/EgovLoginUsr"; |
| 315 | 315 |
}*/ |
| 316 | 316 |
|
| 317 |
+ List<String> authorities = EgovUserDetailsHelper.getAuthorities(); |
|
| 318 |
+ boolean adminYN = false; |
|
| 319 |
+ for (String authority : authorities) {
|
|
| 320 |
+ if (authority.equals("ROLE_ADMIN")) {
|
|
| 321 |
+ adminYN = true; |
|
| 322 |
+ } |
|
| 323 |
+ } |
|
| 324 |
+ |
|
| 317 | 325 |
LoginVO sessionLogin = (LoginVO) EgovUserDetailsHelper.getAuthenticatedUser(); |
| 318 | 326 |
String uniqId = "".equals(userSearchVO.getSelectedId()) ? sessionLogin.getUniqId() : userSearchVO.getSelectedId() ; |
| 327 |
+ |
|
| 328 |
+ if(!adminYN) {
|
|
| 329 |
+ if(!sessionLogin.getUniqId().equals(uniqId)) {
|
|
| 330 |
+ return "redirect:/"; |
|
| 331 |
+ } |
|
| 332 |
+ } |
|
| 319 | 333 |
|
| 320 | 334 |
ComDefaultCodeVO vo = new ComDefaultCodeVO(); |
| 321 | 335 |
|
--- src/main/resources/egovframework/spring/com/context-security.xml
+++ src/main/resources/egovframework/spring/com/context-security.xml
... | ... | @@ -6,6 +6,8 @@ |
| 6 | 6 |
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.2.xsd |
| 7 | 7 |
http://www.egovframe.go.kr/schema/egov-security http://www.egovframe.go.kr/schema/egov-security/egov-security-3.7.xsd"> |
| 8 | 8 |
|
| 9 |
+ |
|
| 10 |
+<security:http pattern="/direct/**" security="none"/> |
|
| 9 | 11 |
<security:http pattern="/css/**" security="none"/> |
| 10 | 12 |
<security:http pattern="/html/**" security="none"/> |
| 11 | 13 |
<security:http pattern="/images/**" security="none"/> |
+++ src/main/webapp/WEB-INF/config/egovframework/springmvc/egov-interceptor-servlet.xml
... | ... | @@ -0,0 +1,17 @@ |
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<beans:beans xmlns="http://www.springframework.org/schema/mvc" | |
| 3 | + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
| 4 | + xmlns:beans="http://www.springframework.org/schema/beans" | |
| 5 | + xmlns:context="http://www.springframework.org/schema/context" | |
| 6 | + xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd | |
| 7 | + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd | |
| 8 | + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> | |
| 9 | + | |
| 10 | + <interceptors> | |
| 11 | + <interceptor> | |
| 12 | + <mapping path="/uss/**"/> | |
| 13 | + <mapping path="/cop/**"/> | |
| 14 | + <beans:bean class="egovframework.com.cmm.InterceptorHandler"/> | |
| 15 | + </interceptor> | |
| 16 | + </interceptors> | |
| 17 | +</beans:beans>(No newline at end of file) |
--- src/main/webapp/WEB-INF/jsp/cmm/uss/umt/EgovUserManage.jsp
+++ src/main/webapp/WEB-INF/jsp/cmm/uss/umt/EgovUserManage.jsp
... | ... | @@ -138,6 +138,11 @@ |
| 138 | 138 |
document.peristalsisForm.submit(); |
| 139 | 139 |
} |
| 140 | 140 |
|
| 141 |
+function fnPeristalsis() {
|
|
| 142 |
+ document.peristalsisForm.action = "<c:url value='/let/itsm/sync/syncOrgchtRefresh.do'/>"; |
|
| 143 |
+ document.peristalsisForm.submit(); |
|
| 144 |
+} |
|
| 145 |
+ |
|
| 141 | 146 |
|
| 142 | 147 |
function linkPage(pageNo){
|
| 143 | 148 |
var searchForm = document.searchForm ; |
+++ src/main/webapp/WEB-INF/jsp/uat/uia/EgovLoginUsr2.jsp
... | ... | @@ -0,0 +1,38 @@ |
| 1 | +<%-- | |
| 2 | + Class Name : EgovLoginUsr.jsp | |
| 3 | + Description : 로그인화면 | |
| 4 | + Modification Information | |
| 5 | + | |
| 6 | + 수정일 수정자 수정내용 | |
| 7 | + ------- -------- --------------------------- | |
| 8 | + 2009.03.10 박지욱 최초 생성 | |
| 9 | + 2011.08.31 JJY 경량환경 버전 생성 | |
| 10 | + | |
| 11 | + author : 공통서비스 개발팀 박지욱 | |
| 12 | + since : 2009.03.10 | |
| 13 | +--%> | |
| 14 | +<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> | |
| 15 | +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> | |
| 16 | +<%@ taglib prefix="ui" uri="http://egovframework.gov/ctl/ui"%> | |
| 17 | +<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> | |
| 18 | +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> | |
| 19 | +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> | |
| 20 | +<!DOCTYPE html> | |
| 21 | +<html lang="ko"> | |
| 22 | +<head> | |
| 23 | +<meta http-equiv="Content-Language" content="ko" > | |
| 24 | +<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
| 25 | +<script src="<c:url value='/js/jquery-1.12.4.min.js' />"></script> | |
| 26 | +<title>로그인</title> | |
| 27 | +<!-- <link href="/css/post.css?ver=1" rel="stylesheet" > --> | |
| 28 | +<script type="text/javascript"> | |
| 29 | +$( document ).ready(function(){ | |
| 30 | + | |
| 31 | + alert("세션이 만료 되었습니다. 재로그인해주세요"); | |
| 32 | + window.close(); | |
| 33 | +}); | |
| 34 | +</script> | |
| 35 | +</head> | |
| 36 | +<body> | |
| 37 | +</body> | |
| 38 | +</html>(No newline at end of file) |
--- src/main/webapp/WEB-INF/jsp/uss/itsm/edu/ConfFileUpload.jsp
+++ src/main/webapp/WEB-INF/jsp/uss/itsm/edu/ConfFileUpload.jsp
... | ... | @@ -160,6 +160,8 @@ |
| 160 | 160 |
success: function(returnData , status){
|
| 161 | 161 |
if(returnData.result == 'auth_fail'){
|
| 162 | 162 |
alert("세션이 종료되었습니다.");
|
| 163 |
+ }else if(returnData.result == 'extension'){
|
|
| 164 |
+ alert("첨부파일 확장자 확인 부탁드립니다.");
|
|
| 163 | 165 |
}else if(returnData.result == 'success'){
|
| 164 | 166 |
$('.upload_box_img').hide(); //list 박스 형식 변경
|
| 165 | 167 |
$('.upload_box_text').hide();
|
--- src/main/webapp/WEB-INF/jsp/uss/itsm/edu/eduPlanView.jsp
+++ src/main/webapp/WEB-INF/jsp/uss/itsm/edu/eduPlanView.jsp
... | ... | @@ -29,7 +29,6 @@ |
| 29 | 29 |
<script src="/direct/js/popup_open_2.js"></script> |
| 30 | 30 |
<script type="text/javascript" src="<c:url value='/js/EgovMultiFile.js'/>"></script> |
| 31 | 31 |
<script type="text/javascript" src="/js/audit/audit.common.js"></script> |
| 32 |
- <%@ taglib prefix="ckeditor" uri="http://ckeditor.com"%> |
|
| 33 | 32 |
|
| 34 | 33 |
<script type="text/javaScript" language="javascript"> |
| 35 | 34 |
|
... | ... | @@ -295,6 +294,8 @@ |
| 295 | 294 |
success: function(returnData , status){
|
| 296 | 295 |
if(returnData.result == 'auth_fail'){
|
| 297 | 296 |
alert("세션이 종료되었습니다.");
|
| 297 |
+ }else if(returnData.result == 'extension'){
|
|
| 298 |
+ alert("첨부파일 확장자 확인 부탁드립니다.");
|
|
| 298 | 299 |
}else if(returnData.result == 'success'){
|
| 299 | 300 |
$('.upload_box_img').hide(); //list 박스 형식 변경
|
| 300 | 301 |
$('.upload_box_text').hide();
|
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?