게시글 제목, 내용에 대한 특수문자(태그포함) 및 XSS 처리 통합자료관과 통일성있게 변경 처리

This commit is contained in:
KNKIM 2021-12-22 10:07:27 +09:00
parent 22f543a91a
commit 3c29a91a59
8 changed files with 1342 additions and 1278 deletions

View File

@ -93,8 +93,8 @@ public class ArticleVO extends PagingVO {
return attachFiles.size(); return attachFiles.size();
} }
public String getUnescapedContent() { public String getSanitizedContent() {
return StringEscapeUtils.unescapeHtml(content); return StringUtil.sanitizeHtml(content);
} }
// SETTER & GETTER // SETTER & GETTER
@ -126,7 +126,14 @@ public class ArticleVO extends PagingVO {
} }
public void setTitle(String title) { public void setTitle(String title) {
this.title = title;
/*
* 통합자료관관리시스템과 동일하게 게시글 저장 처리를 수행하며,
* 제목의 경우, DB에 일부 특수문자에 대하여 치환되어 저장되고,
* 내용의 경우, HTML 요청된 그대로 저장하되 표출할 HTML Sanitizing하여 표출토록 처리하기로 협의됨에 따라
* 제목 설정시 치환되어 저장토록 (2021.12.21, 이규모차장님)
*/
this.title = StringUtil.getRemovedQuotesStr(title);
} }
public String getContent() { public String getContent() {
return content; return content;
@ -287,6 +294,10 @@ public class ArticleVO extends PagingVO {
return answer; return answer;
} }
public String getSanitizedAnswer() {
return StringUtil.sanitizeHtml(answer);
}
public void setAnswer(String answer) { public void setAnswer(String answer) {
this.answer = answer; this.answer = answer;
} }

View File

@ -137,6 +137,12 @@ public class FaqController extends NlibCommonController {
// 읽음처리 상세내용 조회 // 읽음처리 상세내용 조회
ArticleVO articleVO = faqService.selectArticle(searchArticleVO); ArticleVO articleVO = faqService.selectArticle(searchArticleVO);
// AJAX OUT에 XSS처리되지 않은 HTML 전송 차단위한 변경 처리
if(articleVO != null) {
articleVO.setAnswer(articleVO.getSanitizedAnswer());
articleVO.setContent(articleVO.getSanitizedContent());
}
//------------------------------- //-------------------------------
// JSON변환 응답 처리 // JSON변환 응답 처리
//------------------------------- //-------------------------------

View File

@ -273,6 +273,45 @@ public class StringUtil extends StringUtils {
return str; return str;
} }
/**
* 게시글 제목 허용되지 말아야하는 일부 특수문자에 대한 치환 처리하여 리턴
*
* @param val
* @return
*/
public static String getRemovedQuotesStr(String val) {
if (isEmpty(val)) return val;
StringBuffer strBuff = new StringBuffer();
for (int j = 0; j < val.length(); j++) {
char c = val.charAt(j);
switch (c) {
case '<':
strBuff.append("");
break;
case '>':
strBuff.append("");
break;
case '&':
strBuff.append("");
break;
case '"':
strBuff.append("");
break;
case '\'':
strBuff.append("");
break;
default:
strBuff.append(c);
break;
}
}
return strBuff.toString();
}
/** /**
* 날짜 문자열(YYYYMMDD) 받아서 화면 출력용 날짜 형식 문자열(YYYY-MM-DD) 리턴한다. * 날짜 문자열(YYYYMMDD) 받아서 화면 출력용 날짜 형식 문자열(YYYY-MM-DD) 리턴한다.
* *
@ -391,7 +430,9 @@ public class StringUtil extends StringUtils {
* @param html * @param html
* @return * @return
*/ */
private static String sanitizeHtml(String html) { public static String sanitizeHtml(String html) {
if(isEmpty(html)) return html;
PolicyFactory policy = new HtmlPolicyBuilder() PolicyFactory policy = new HtmlPolicyBuilder()
.allowAttributes("src", "align", "title").onElements("img") .allowAttributes("src", "align", "title").onElements("img")

View File

@ -342,7 +342,7 @@ function fn_downloadFile(attachFileId, fileSn) {
<li class="wt-question"> <li class="wt-question">
<div class="w-tit">내용 <span class="required">*</span></div> <div class="w-tit">내용 <span class="required">*</span></div>
<div class="w-form"> <div class="w-form">
<textarea name="content" id="content" cols="80" rows="10" placeholder="질문하실 내용을 입력하세요." style="width:100%;min-width:260px;"><c:out value='${searchArticle.unescapedContent}' escapeXml='false' /></textarea> <textarea name="content" id="content" cols="80" rows="10" placeholder="질문하실 내용을 입력하세요." style="width:100%;min-width:260px;"><c:out value='${searchArticle.sanitizedContent}' escapeXml='false' /></textarea>
</div> </div>
</li> </li>
</ul> </ul>

View File

@ -121,7 +121,7 @@ function fn_downloadFile(attachFileId, fileSn) {
<div class="view-body"> <div class="view-body">
<div class="view-con"> <div class="view-con">
<div class="view-txt"> <div class="view-txt">
<c:out value='${article.content}' escapeXml='false' /> <c:out value='${article.sanitizedContent}' escapeXml='false' />
</div> </div>
</div> </div>
<ul class="attachments"> <ul class="attachments">

View File

@ -145,7 +145,7 @@ function fn_downloadFile(attachFileId, fileSn) {
<div class="view-con"> <div class="view-con">
<div class="view-txt"> <div class="view-txt">
<p> <p>
<c:out value='${article.unescapedContent}' escapeXml="false" /> <c:out value='${article.sanitizedContent}' escapeXml='false' />
</p> </p>
</div> </div>
</div> </div>
@ -156,7 +156,7 @@ function fn_downloadFile(attachFileId, fileSn) {
<span class="right"><c:out value='${article.modDd }'/></span> <span class="right"><c:out value='${article.modDd }'/></span>
</div> </div>
<div class="answer-con"> <div class="answer-con">
<p><c:out value='${article.answer}' escapeXml = 'false' /></p> <p><c:out value='${article.sanitizedAnswer}' escapeXml = 'false' /></p>
</div> </div>
</div> </div>
</c:if> </c:if>

View File

@ -62,6 +62,9 @@ $( document ).ready(function() {
var $qObj = $(qObj); var $qObj = $(qObj);
if($qObj.hasClass('on')) { if($qObj.hasClass('on')) {
$qObj.removeClass("on");
$qObj.next(".answer").stop().slideUp(300);
$qObj.next(".answer").html("");
return; return;
} }

View File

@ -20,6 +20,8 @@
<url-pattern>*.do</url-pattern> <url-pattern>*.do</url-pattern>
</filter-mapping> </filter-mapping>
<!-- 별도 OWASP HTML Sanitizer 사용으로 대체 -->
<!--
<filter> <filter>
<filter-name>HTMLTagFilter</filter-name> <filter-name>HTMLTagFilter</filter-name>
<filter-class>egovframework.rte.ptl.mvc.filter.HTMLTagFilter</filter-class> <filter-class>egovframework.rte.ptl.mvc.filter.HTMLTagFilter</filter-class>
@ -28,6 +30,7 @@
<filter-name>HTMLTagFilter</filter-name> <filter-name>HTMLTagFilter</filter-name>
<url-pattern>*.do</url-pattern> <url-pattern>*.do</url-pattern>
</filter-mapping> </filter-mapping>
-->
<!-- Spring Security Filter : DIGITALSHIP 2021.07.02 --> <!-- Spring Security Filter : DIGITALSHIP 2021.07.02 -->
<filter> <filter>