diff --git a/jwtech-admin/src/main/java/com/kms/Test.java b/jwtech-admin/src/main/java/com/kms/Test.java new file mode 100644 index 00000000..25413289 --- /dev/null +++ b/jwtech-admin/src/main/java/com/kms/Test.java @@ -0,0 +1,13 @@ +package com.kms; + + +import cn.hutool.core.util.EscapeUtil; + +public class Test { + public static void main(String[] args) { + String html = ""; + System.out.println(EscapeUtil.escape(html)); + System.out.println(EscapeUtil.escape(html)); + System.out.println(EscapeUtil.unescape(html)); + } +} diff --git a/jwtech-framework/src/main/java/com/jianwei/common/filter/XssHttpServletRequestWrapper.java b/jwtech-framework/src/main/java/com/jianwei/common/filter/XssHttpServletRequestWrapper.java index 7eda7e85..b4ea31df 100644 --- a/jwtech-framework/src/main/java/com/jianwei/common/filter/XssHttpServletRequestWrapper.java +++ b/jwtech-framework/src/main/java/com/jianwei/common/filter/XssHttpServletRequestWrapper.java @@ -6,6 +6,8 @@ import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; + +import com.jianwei.common.utils.XssUtils; import org.apache.commons.io.IOUtils; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; @@ -63,7 +65,8 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper } // xss过滤 - json = EscapeUtil.clean(json).trim(); +// json = EscapeUtil.clean(json).trim(); + json = XssUtils.xssContent(json).trim(); final ByteArrayInputStream bis = new ByteArrayInputStream(json.getBytes("utf-8")); return new ServletInputStream() { diff --git a/jwtech-framework/src/main/java/com/jianwei/common/utils/UrlFileUtil.java b/jwtech-framework/src/main/java/com/jianwei/common/utils/UrlFileUtil.java index d33b0cb9..846fe2f4 100644 --- a/jwtech-framework/src/main/java/com/jianwei/common/utils/UrlFileUtil.java +++ b/jwtech-framework/src/main/java/com/jianwei/common/utils/UrlFileUtil.java @@ -6,7 +6,7 @@ import java.io.*; import java.net.HttpURLConnection; import java.net.URL; -public class UrlFileUtil { +public class UrlFileUtil { /** * 从网络Url中下载文件 diff --git a/jwtech-framework/src/main/java/com/jianwei/common/utils/XssFilterUtils.java b/jwtech-framework/src/main/java/com/jianwei/common/utils/XssFilterUtils.java new file mode 100644 index 00000000..5cd6d03e --- /dev/null +++ b/jwtech-framework/src/main/java/com/jianwei/common/utils/XssFilterUtils.java @@ -0,0 +1,112 @@ +package com.jianwei.common.utils; + +import java.util.regex.Pattern; + +import java.util.regex.Matcher; +public class XssFilterUtils { + private static final String HTML_ESCAPE_REGEX = "[&\"'<>`]"; + private static final String[] HTML_ESCAPE_REPLACEMENTS = {"&", """, "<", ">", "'", ">"}; + + private static final Pattern SCRIPT_PATTERN = Pattern.compile( + "<\\s*script\\s*.*?>", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + private static final Pattern EVENT_HANDLER_PATTERN = Pattern.compile( + "on\\w+\\s*=\\s*['\"]?.*?['\"]?", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + private static final Pattern DANGEROUS_PROTOCOL_PATTERN = Pattern.compile( + "(javascript|vbscript|data|file|about|chrome|moz-extension):", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + private static final Pattern CSS_EXPRESSION_PATTERN = Pattern.compile( + "expression\\s*\\(|url\\s*\\([^\\)]*?javascript:", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); + + private XssFilterUtils() { + throw new IllegalStateException("Utility class"); + } + + public static String filter(String input) { + if (input == null || input.isEmpty()) { + return input; + } + + String processed = input.trim(); + processed = sanitizeHtmlTags(processed); + processed = sanitizeEventHandlers(processed); + processed = sanitizeDangerousProtocols(processed); + processed = sanitizeCssExpressions(processed); + processed = escapeHtmlCharacters(processed); + + return processed; + } + + private static String sanitizeHtmlTags(String input) { + return SCRIPT_PATTERN.matcher(input).replaceAll(""); + } + + private static String sanitizeEventHandlers(String input) { + return EVENT_HANDLER_PATTERN.matcher(input).replaceAll(""); + } + + private static String sanitizeDangerousProtocols(String input) { + Matcher matcher = DANGEROUS_PROTOCOL_PATTERN.matcher(input); + StringBuffer result = new StringBuffer(); + while (matcher.find()) { + String protocol = matcher.group(1).toLowerCase(); + matcher.appendReplacement(result, protocol + "://"); + } + matcher.appendTail(result); + return result.toString(); + } + + private static String sanitizeCssExpressions(String input) { + return CSS_EXPRESSION_PATTERN.matcher(input).replaceAll(""); + } + + private static String escapeHtmlCharacters(String input) { + Matcher matcher = Pattern.compile(HTML_ESCAPE_REGEX).matcher(input); + StringBuffer result = new StringBuffer(); + while (matcher.find()) { + char c = matcher.group().charAt(0); + String replacement; + switch (c) { + case '&': + replacement = HTML_ESCAPE_REPLACEMENTS[0]; + break; + case '"': + replacement = HTML_ESCAPE_REPLACEMENTS[1]; + break; + case '<': + replacement = HTML_ESCAPE_REPLACEMENTS[2]; + break; + case '>': + replacement = HTML_ESCAPE_REPLACEMENTS[3]; + break; + case '\'': + replacement = HTML_ESCAPE_REPLACEMENTS[4]; + break; + case '`': + replacement = HTML_ESCAPE_REPLACEMENTS[5]; + break; + default: + replacement = matcher.group(); + } + matcher.appendReplacement(result, replacement); + } + matcher.appendTail(result); + return result.toString(); + } + + public static void main(String[] args) { + // 测试用例 + String[] testCases = { + "", + "click me", + "
hover me
", + "", + "expression(alert(4))", + "url(javascript:alert(5))" + }; + + for (String testCase : testCases) { + System.out.println("原始输入: " + testCase); + System.out.println("过滤后: " + filter(testCase)); + System.out.println("------------------------"); + } + } +} diff --git a/jwtech-framework/src/main/java/com/jianwei/common/utils/XssUtils.java b/jwtech-framework/src/main/java/com/jianwei/common/utils/XssUtils.java new file mode 100644 index 00000000..51d0b98b --- /dev/null +++ b/jwtech-framework/src/main/java/com/jianwei/common/utils/XssUtils.java @@ -0,0 +1,208 @@ +package com.jianwei.common.utils; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.safety.Safelist; + +import java.util.regex.Pattern; + +public class XssUtils { + private static final Pattern[] XSS_PATTERNS = { + // 避免 script 标签 + Pattern.compile("", Pattern.CASE_INSENSITIVE), + Pattern.compile("", Pattern.CASE_INSENSITIVE), + Pattern.compile("", Pattern.CASE_INSENSITIVE), + Pattern.compile("