From 9fafeecd059b76f2a985a840423ed676a3bcd6f8 Mon Sep 17 00:00:00 2001 From: KNKIM Date: Wed, 22 Dec 2021 11:27:42 +0900 Subject: [PATCH] =?UTF-8?q?html=20sanitizing=20=EB=B3=B4=EC=99=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/nlib/util/StringUtil.java | 89 +++++++++++++++++-------- 1 file changed, 60 insertions(+), 29 deletions(-) diff --git a/src/main/java/nlib/util/StringUtil.java b/src/main/java/nlib/util/StringUtil.java index dd945d76..a8fb28ab 100644 --- a/src/main/java/nlib/util/StringUtil.java +++ b/src/main/java/nlib/util/StringUtil.java @@ -11,6 +11,7 @@ import java.util.Base64; import java.util.Base64.Decoder; import java.util.Base64.Encoder; import java.util.Locale; +import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.owasp.html.HtmlPolicyBuilder; @@ -18,6 +19,8 @@ import org.owasp.html.PolicyFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.base.Predicate; + import nlib.cmm.service.NlibProperty; /** @@ -423,36 +426,7 @@ public class StringUtil extends StringUtils { return value; } - - /** - * XSS 등의 공격으로 부터 보안성 유지를 위해서 HTML 허용된 태그와 속성만으로 HTML을 재구성하여 리턴한다. - * - * @param html - * @return - */ - public static String sanitizeHtml(String html) { - - if(isEmpty(html)) return html; - PolicyFactory policy = new HtmlPolicyBuilder() - .allowAttributes("src", "align", "title").onElements("img") - .allowAttributes("href", "title").onElements("a") - .allowAttributes("class", "height", "width", "style").globally() - .allowUrlProtocols("http","https","mailto","tel") - .allowElements( - "a", "label", - "h1", "h2", "h3", "h4", "h5", "h6", - "p", "i", "b", "u", "strong", "em", "small", "big", "pre", "code", - "cite", "samp", "sub", "sup", "strike", "center", "blockquote", - "hr", "br", "col", "font", "span", "div", "img", - "ul", "ol", "li", "dd", "dt", "dl", "tbody", "thead", "tfoot", - "table", "td", "th", "tr", "colgroup", "fieldset", "legend" - ) - .toFactory(); - - return policy.sanitize(html); - } - // Tag 화이트 리스트 ( 허용할 태그 등록 ) static String[] whiteListTag = { "

","

","
" }; @@ -494,4 +468,61 @@ public class StringUtil extends StringUtils { return false; } + /* + ************************************************************************************************ + * OWASP HTML SANITIZING 관련 : 시작 + ************************************************************************************************ + */ + private static final Pattern ONSITE_URL = Pattern.compile("(?:[\\p{L}\\p{N}\\\\\\.\\#@\\$%\\+&;\\-_~,\\?=/!]+|\\#(\\w)+)"); + private static final Pattern OFFSITE_URL = Pattern.compile("\\s*(?:(?:ht|f)tps?://|mailto:)[\\p{L}\\p{N}]" + + "[\\p{L}\\p{N}\\p{Zs}\\.\\#@\\$%\\+&;:\\-_~,\\?=/!\\(\\)]*+\\s*"); + private static final Pattern EMBED_URL = Pattern.compile("^.*data:image/.*$"); + + private static final Predicate ONSITE_OR_OFFSITE_URL = matchesEither(ONSITE_URL, OFFSITE_URL, EMBED_URL); + + /** + * XSS 등의 공격으로 부터 보안성 유지를 위해서 HTML 허용된 태그와 속성만으로 HTML을 재구성하여 리턴한다. + * + * @param html + * @return + */ + public static String sanitizeHtml(String html) { + + if(isEmpty(html)) return html; + + PolicyFactory policy = new HtmlPolicyBuilder() + .allowAttributes("src", "align", "title").onElements("img") + .allowAttributes("href", "title").onElements("a") + .allowAttributes("class", "height", "width", "style").globally() + .allowUrlProtocols("http","https","mailto","tel","data") + .allowAttributes("src").matching(ONSITE_OR_OFFSITE_URL).onElements("img") + .allowAttributes("src").matching(Pattern.compile("^.*data:image/.*$")).onElements("img") + .allowElements( + "a", "label", + "h1", "h2", "h3", "h4", "h5", "h6", + "p", "i", "b", "u", "strong", "em", "small", "big", "pre", "code", + "cite", "samp", "sub", "sup", "strike", "center", "blockquote", + "hr", "br", "col", "font", "span", "div", "img", + "ul", "ol", "li", "dd", "dt", "dl", "tbody", "thead", "tfoot", + "table", "td", "th", "tr", "colgroup", "fieldset", "legend" + ) + .toFactory(); + + return policy.sanitize(html); + } + + private static Predicate matchesEither(final Pattern a, final Pattern b, final Pattern c) { + return new Predicate() { + public boolean apply(String s) { + return a.matcher(s).matches() || b.matcher(s).matches() || c.matcher(s).matches(); + } + }; + } + + /* + ************************************************************************************************ + * OWASP HTML SANITIZING 관련 : 종료 + ************************************************************************************************ + */ + }