diff --git a/kicc-common/kicc-common-core/src/main/java/com/cloud/kicc/common/core/util/HTMLFilterUtil.java b/kicc-common/kicc-common-core/src/main/java/com/cloud/kicc/common/core/util/HTMLFilterUtil.java index 776bef3a..4fa2ca4b 100644 --- a/kicc-common/kicc-common-core/src/main/java/com/cloud/kicc/common/core/util/HTMLFilterUtil.java +++ b/kicc-common/kicc-common-core/src/main/java/com/cloud/kicc/common/core/util/HTMLFilterUtil.java @@ -205,112 +205,112 @@ public final class HTMLFilterUtil { return s; } - public boolean isAlwaysMakeTags() { - return alwaysMakeTags; - } - - public boolean isStripComments() { - return stripComment; - } - - private String escapeComments(final String s) { - final Matcher m = P_COMMENTS.matcher(s); - final StringBuffer buf = new StringBuffer(); - if (m.find()) { - final String match = m.group(1); // (.*?) - m.appendReplacement(buf, Matcher.quoteReplacement("")); - } - m.appendTail(buf); - - return buf.toString(); - } - - private String balanceHTML(String s) { - if (alwaysMakeTags) { - // - // try and form html - // - s = regexReplace(P_END_ARROW, "", s); - s = regexReplace(P_BODY_TO_END, "<$1>", s); - s = regexReplace(P_XML_CONTENT, "$1<$2", s); - - } else { - // - // escape stray brackets - // - s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); - s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); - - // - // the last regexp causes '<>' entities to appear - // (we need to do a lookahead assertion so that the last bracket can - // be used in the next pass of the regexp) - // - s = regexReplace(P_BOTH_ARROWS, "", s); - } - - return s; - } - - private String checkTags(String s) { - Matcher m = P_TAGS.matcher(s); - - final StringBuffer buf = new StringBuffer(); - while (m.find()) { - String replaceStr = m.group(1); - replaceStr = processTag(replaceStr); - m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); - } - m.appendTail(buf); - - // these get tallied in processTag - // (remember to reset before subsequent calls to filter method) - final StringBuilder sBuilder = new StringBuilder(buf.toString()); - for (String key : vTagCounts.keySet()) { - for (int ii = 0; ii < vTagCounts.get(key); ii++) { - sBuilder.append(""); - } - } - s = sBuilder.toString(); - - return s; - } - - private String processRemoveBlanks(final String s) { - String result = s; - for (String tag : vRemoveBlanks) { - if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) { - P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); - } - result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); - if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) { - P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); - } - result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); - } - - return result; - } - - private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) { - Matcher m = regex_pattern.matcher(s); - return m.replaceAll(replacement); - } - - private String processTag(final String s) { - // ending tags - Matcher m = P_END_TAG.matcher(s); - if (m.find()) { - final String name = m.group(1).toLowerCase(); - if (allowed(name)) { - if (false == inArray(name, vSelfClosingTags)) { - if (vTagCounts.containsKey(name)) { - vTagCounts.put(name, vTagCounts.get(name) - 1); - return ""; - } - } - } - } + public boolean isAlwaysMakeTags() { + return alwaysMakeTags; + } + + public boolean isStripComments() { + return stripComment; + } + + private String escapeComments(final String s) { + final Matcher m = P_COMMENTS.matcher(s); + final StringBuffer buf = new StringBuffer(); + if (m.find()) { + final String match = m.group(1); // (.*?) + m.appendReplacement(buf, Matcher.quoteReplacement("")); + } + m.appendTail(buf); + + return buf.toString(); + } + + private String balanceHTML(String s) { + if (alwaysMakeTags) { + // + // try and form html + // + s = regexReplace(P_END_ARROW, "", s); + s = regexReplace(P_BODY_TO_END, "<$1>", s); + s = regexReplace(P_XML_CONTENT, "$1<$2", s); + + } else { + // + // escape stray brackets + // + s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s); + s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s); + + // + // the last regexp causes '<>' entities to appear + // (we need to do a lookahead assertion so that the last bracket can + // be used in the next pass of the regexp) + // + s = regexReplace(P_BOTH_ARROWS, "", s); + } + + return s; + } + + private String checkTags(String s) { + Matcher m = P_TAGS.matcher(s); + + final StringBuffer buf = new StringBuffer(); + while (m.find()) { + String replaceStr = m.group(1); + replaceStr = processTag(replaceStr); + m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr)); + } + m.appendTail(buf); + + // these get tallied in processTag + // (remember to reset before subsequent calls to filter method) + final StringBuilder sBuilder = new StringBuilder(buf.toString()); + for (String key : vTagCounts.keySet()) { + for (int ii = 0; ii < vTagCounts.get(key); ii++) { + sBuilder.append(""); + } + } + s = sBuilder.toString(); + + return s; + } + + private String processRemoveBlanks(final String s) { + String result = s; + for (String tag : vRemoveBlanks) { + if (!P_REMOVE_PAIR_BLANKS.containsKey(tag)) { + P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?>")); + } + result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result); + if (!P_REMOVE_SELF_BLANKS.containsKey(tag)) { + P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>")); + } + result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result); + } + + return result; + } + + private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s) { + Matcher m = regex_pattern.matcher(s); + return m.replaceAll(replacement); + } + + private String processTag(final String s) { + // ending tags + Matcher m = P_END_TAG.matcher(s); + if (m.find()) { + final String name = m.group(1).toLowerCase(); + if (allowed(name)) { + if (false == inArray(name, vSelfClosingTags)) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) - 1); + return ""; + } + } + } + } // starting tags m = P_START_TAG.matcher(s); @@ -353,105 +353,105 @@ public final class HTMLFilterUtil { } } - if (inArray(name, vSelfClosingTags)) { - ending = " /"; - } - - if (inArray(name, vNeedClosingTags)) { - ending = ""; - } - - if (ending == null || ending.length() < 1) { - if (vTagCounts.containsKey(name)) { - vTagCounts.put(name, vTagCounts.get(name) + 1); - } else { - vTagCounts.put(name, 1); - } - } else { - ending = " /"; - } - return "<" + name + params + ending + ">"; - } else { - return ""; - } - } - - // comments - m = P_COMMENT.matcher(s); - if (!stripComment && m.find()) { - return "<" + m.group() + ">"; - } - - return ""; - } - - private String processParamProtocol(String s) { - s = decodeEntities(s); - final Matcher m = P_PROTOCOL.matcher(s); - if (m.find()) { - final String protocol = m.group(1); - if (!inArray(protocol, vAllowedProtocols)) { - // bad protocol, turn into local anchor link instead - s = "#" + s.substring(protocol.length() + 1); - if (s.startsWith("#//")) { - s = "#" + s.substring(3); - } - } - } - - return s; - } - - private String decodeEntities(String s) { - StringBuffer buf = new StringBuffer(); - - Matcher m = P_ENTITY.matcher(s); - while (m.find()) { - final String match = m.group(1); - final int decimal = Integer.decode(match).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - buf = new StringBuffer(); - m = P_ENTITY_UNICODE.matcher(s); - while (m.find()) { - final String match = m.group(1); - final int decimal = Integer.valueOf(match, 16).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - buf = new StringBuffer(); - m = P_ENCODE.matcher(s); - while (m.find()) { - final String match = m.group(1); - final int decimal = Integer.valueOf(match, 16).intValue(); - m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); - } - m.appendTail(buf); - s = buf.toString(); - - s = validateEntities(s); - return s; - } - - private String validateEntities(final String s) { - StringBuffer buf = new StringBuffer(); - - // validate entities throughout the string - Matcher m = P_VALID_ENTITIES.matcher(s); - while (m.find()) { - final String one = m.group(1); // ([^&;]*) - final String two = m.group(2); // (?=(;|&|$)) - m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); - } - m.appendTail(buf); - - return encodeQuotes(buf.toString()); - } + if (inArray(name, vSelfClosingTags)) { + ending = " /"; + } + + if (inArray(name, vNeedClosingTags)) { + ending = ""; + } + + if (ending == null || ending.length() < 1) { + if (vTagCounts.containsKey(name)) { + vTagCounts.put(name, vTagCounts.get(name) + 1); + } else { + vTagCounts.put(name, 1); + } + } else { + ending = " /"; + } + return "<" + name + params + ending + ">"; + } else { + return ""; + } + } + + // comments + m = P_COMMENT.matcher(s); + if (!stripComment && m.find()) { + return "<" + m.group() + ">"; + } + + return ""; + } + + private String processParamProtocol(String s) { + s = decodeEntities(s); + final Matcher m = P_PROTOCOL.matcher(s); + if (m.find()) { + final String protocol = m.group(1); + if (!inArray(protocol, vAllowedProtocols)) { + // bad protocol, turn into local anchor link instead + s = "#" + s.substring(protocol.length() + 1); + if (s.startsWith("#//")) { + s = "#" + s.substring(3); + } + } + } + + return s; + } + + private String decodeEntities(String s) { + StringBuffer buf = new StringBuffer(); + + Matcher m = P_ENTITY.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.decode(match); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENTITY_UNICODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.parseInt(match, 16); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + buf = new StringBuffer(); + m = P_ENCODE.matcher(s); + while (m.find()) { + final String match = m.group(1); + final int decimal = Integer.parseInt(match, 16); + m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal))); + } + m.appendTail(buf); + s = buf.toString(); + + s = validateEntities(s); + return s; + } + + private String validateEntities(final String s) { + StringBuffer buf = new StringBuffer(); + + // validate entities throughout the string + Matcher m = P_VALID_ENTITIES.matcher(s); + while (m.find()) { + final String one = m.group(1); // ([^&;]*) + final String two = m.group(2); // (?=(;|&|$)) + m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two))); + } + m.appendTail(buf); + + return encodeQuotes(buf.toString()); + } private String encodeQuotes(final String s) { if (encodeQuotes) { @@ -471,29 +471,29 @@ public final class HTMLFilterUtil { } } - private String checkEntity(final String preamble, final String term) { + private String checkEntity(final String preamble, final String term) { - return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; - } + return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble; + } - private boolean isValidEntity(final String entity) { - return inArray(entity, vAllowedEntities); - } + private boolean isValidEntity(final String entity) { + return inArray(entity, vAllowedEntities); + } - private static boolean inArray(final String s, final String[] array) { - for (String item : array) { - if (item != null && item.equals(s)) { - return true; - } - } - return false; - } + private static boolean inArray(final String s, final String[] array) { + for (String item : array) { + if (item != null && item.equals(s)) { + return true; + } + } + return false; + } - private boolean allowed(final String name) { - return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); - } + private boolean allowed(final String name) { + return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed); + } - private boolean allowedAttribute(final String name, final String paramName) { - return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); - } + private boolean allowedAttribute(final String name, final String paramName) { + return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName)); + } } diff --git a/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/xss/XssHttpServletRequestWrapper.java b/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/xss/XssHttpServletRequestWrapper.java index c07c97fa..7ca4a885 100644 --- a/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/xss/XssHttpServletRequestWrapper.java +++ b/kicc-common/kicc-common-security/src/main/java/com/cloud/kicc/common/security/xss/XssHttpServletRequestWrapper.java @@ -17,6 +17,7 @@ import java.io.IOException; /** *

+ * 扩展 Security 默认 StrictHttpFirewall(XSS)脚本攻击过滤 * XSS、sql过滤处理 *

* @@ -26,10 +27,11 @@ import java.io.IOException; @Slf4j public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { - private static String[] SQL_KEYWORDS = {"master", "truncate", "insert", "select" + private static final String[] SQL_KEYWORDS = {"master", "truncate", "insert", "select" , "delete", "update", "declare", "alter", "drop", "sleep"}; - //sql 替换字符 - private static String REPLACE_STR = ""; + + // sql 替换字符 + private static final String REPLACE_STR = ""; /** * @param request @@ -43,18 +45,22 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { String[] values = super.getParameterValues(name); if (values != null) { int length = values.length; - String[] escapseValues = new String[length]; + String[] escapeValues = new String[length]; for (int i = 0; i < length; i++) { - // 防xss攻击和过滤前后空格 - escapseValues[i] = HtmlUtil.filter(values[i]).trim(); - //防sql注入 - escapseValues[i] = cleanSqlKeyWords(escapseValues[i]); + // 防xss攻击和过滤html相关脚本 + escapeValues[i] = HtmlUtil.filter(values[i]).trim(); + // 防sql注入 + escapeValues[i] = cleanSqlKeyWords(escapeValues[i]); } - return escapseValues; + return escapeValues; } return super.getParameterValues(name); } + public static void main(String[] args) { + System.out.println(new HTMLFilterUtil().filter("

123

").trim()); + } + private String cleanSqlKeyWords(String value) { String paramValue = value; for (String keyword : SQL_KEYWORDS) {