From d2aff7376ac1d7d9a92011870bb4d7c5e6e8ef0c Mon Sep 17 00:00:00 2001 From: pandaapo <1052156701@qq.com> Date: Fri, 29 Jul 2022 23:48:40 +0800 Subject: [PATCH 1/2] Fix the code analysis error mentioned in issue #462: (1) Append space in string literal. (2) Guard against cross-site scripting. --- .../PolarisPropertySourceAutoRefresher.java | 2 +- .../example/xss/XssResponseBodyAdvice.java | 57 ++++++ .../gateway/example/callee/xss/XssFilter.java | 23 +++ .../xss/XssHttpServletRequestWrapper.java | 173 ++++++++++++++++++ .../gateway/example/callee/xss/XssFilter.java | 23 +++ .../xss/XssHttpServletRequestWrapper.java | 171 +++++++++++++++++ .../polaris/router/example/xss/XssFilter.java | 23 +++ .../xss/XssHttpServletRequestWrapper.java | 144 +++++++++++++++ .../polaris/router/example/xss/XssFilter.java | 23 +++ .../xss/XssHttpServletRequestWrapper.java | 140 ++++++++++++++ 10 files changed, 778 insertions(+), 1 deletion(-) create mode 100644 spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/xss/XssResponseBodyAdvice.java create mode 100644 spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java create mode 100644 spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java create mode 100644 spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java create mode 100644 spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java create mode 100644 spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java create mode 100644 spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java create mode 100644 spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java create mode 100644 spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java diff --git a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisPropertySourceAutoRefresher.java b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisPropertySourceAutoRefresher.java index fd70a8fa9..e24dbb434 100644 --- a/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisPropertySourceAutoRefresher.java +++ b/spring-cloud-starter-tencent-polaris-config/src/main/java/com/tencent/cloud/polaris/config/adapter/PolarisPropertySourceAutoRefresher.java @@ -115,7 +115,7 @@ public class PolarisPropertySourceAutoRefresher LOGGER.info( "[SCT Config] received polaris config change event and will refresh spring context." - + "namespace = {}, group = {}, fileName = {}", + + " namespace = {}, group = {}, fileName = {}", polarisPropertySource.getNamespace(), polarisPropertySource.getGroup(), polarisPropertySource.getFileName()); diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/xss/XssResponseBodyAdvice.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/xss/XssResponseBodyAdvice.java new file mode 100644 index 000000000..ffd17754a --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/xss/XssResponseBodyAdvice.java @@ -0,0 +1,57 @@ +package com.tencent.cloud.polaris.circuitbreaker.example.xss; + +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Escape String in ResponseBody before write it into HttpResponse + * + * @author Daifu Wu + */ +@ControllerAdvice +public class XssResponseBodyAdvice implements ResponseBodyAdvice { + + @Override + public boolean supports(MethodParameter methodParameter, Class aClass) { + return methodParameter.hasMethodAnnotation(ResponseBody.class) || methodParameter.getDeclaringClass().getAnnotation(ResponseBody.class) != null || methodParameter.getDeclaringClass().getAnnotation(RestController.class) != null; + } + + @Override + public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { + if (body instanceof String) { + body = StringEscapeUtils.escapeHtml((String)body); + return body; + } + try { + if (!((Class)body.getClass().getField("TYPE").get(null)).isPrimitive()) { + Map map = new HashMap<>(); + Field[] fields = body.getClass().getDeclaredFields(); + for (Field field: fields) { + field.setAccessible(true); + Object value = field.get(body); + if (value instanceof String) { + value = StringEscapeUtils.escapeHtml((String) value); + } + map.put(field.getName(), value); + } + return map; + } + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + return body; + } +} diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java new file mode 100644 index 000000000..3735059cd --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java @@ -0,0 +1,23 @@ +package com.tencent.cloud.polaris.gateway.example.callee.xss; + +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * filter request aim at defending against XSS + * + * @author Daifu Wu + */ +@WebFilter(urlPatterns = "/*", filterName = "xssFilter") +@Component +public class XssFilter implements Filter { + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + filterChain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse); + } +} diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..60f2c28f8 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java @@ -0,0 +1,173 @@ +package com.tencent.cloud.polaris.gateway.example.callee.xss; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.web.servlet.HandlerMapping; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * Wrap HttpServletRequest to escape String arguments + * + * @author Daifu Wu + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private byte[] requestBody; + + public XssHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + BufferedReader reader = request.getReader(); + StringBuilder stringBuilder = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + if (stringBuilder.length() > 0) { + String json = stringBuilder.toString(); + ObjectMapper objectMapper = new ObjectMapper(); + Map map = objectMapper.readValue(json, Map.class); + map.forEach((k, v) -> { + if (v instanceof String) { + v = cleanXSS((String) v); + map.put(k, v); + } + }); + json = objectMapper.writeValueAsString(map); + requestBody = json.getBytes(); + } + } + + /** + * Handles arguments annotated by @RequestBody + * + * @return + * @throws IOException + */ + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } + + /** + * Handles arguments annotated by @RequestParam + * + * @param name + * @return + */ + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (values != null && values.length > 0) { + String[] safeValues = new String[values.length]; + for (int i = 0; i < values.length; i++) { + safeValues[i] = cleanXSS(values[i]); + } + return safeValues; + } + return values; + } + + /** + * Handles arguments annotated by @PathVariable + * + * @param name + * @return + */ + @Override + public Object getAttribute(String name) { + Object value = super.getAttribute(name); + if (name.equalsIgnoreCase(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) && value != null && value instanceof Map) { + ((Map) value).forEach((k, v) -> { + if (v instanceof String) { + v = cleanXSS((String) v); + ((Map) value).put(k, v); + } + }); + } + return value; + } + + /** + * Handles arguments annotated by @RequestHeader + * + * @param name + * @return + */ + @Override + public Enumeration getHeaders(String name) { + List list = Collections.list(super.getHeaders(name)); + list = list.stream().map((e) -> { + ObjectMapper objectMapper = new ObjectMapper(); + try { + Map map = objectMapper.readValue(e, Map.class); + map.forEach((k, v) -> { + v = cleanXSS(v); + map.put(k, v); + }); + e = objectMapper.writeValueAsString(map); + } catch (JsonProcessingException e1) { + e1.printStackTrace(); + } + return e; + }).collect(Collectors.toList()); + return Collections.enumeration(list); + } + + @Override + public String getParameter(String name) { + String value = super.getParameter(name); + if (value != null) { + value = cleanXSS(value); + } + return value; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + /** + * Escape string to defend against XSS + * + * @param value + */ + private String cleanXSS(String value) { + value = StringEscapeUtils.escapeHtml(value); + return value; + } +} diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java new file mode 100644 index 000000000..3735059cd --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java @@ -0,0 +1,23 @@ +package com.tencent.cloud.polaris.gateway.example.callee.xss; + +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * filter request aim at defending against XSS + * + * @author Daifu Wu + */ +@WebFilter(urlPatterns = "/*", filterName = "xssFilter") +@Component +public class XssFilter implements Filter { + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + filterChain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse); + } +} diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..6b51a2978 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java @@ -0,0 +1,171 @@ +package com.tencent.cloud.polaris.gateway.example.callee.xss; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.web.servlet.HandlerMapping; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Wrap HttpServletRequest to escape String arguments + * + * @author Daifu Wu + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private byte[] requestBody; + + public XssHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + BufferedReader reader = request.getReader(); + StringBuilder stringBuilder = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + if (stringBuilder.length() > 0) { + String json = stringBuilder.toString(); + ObjectMapper objectMapper = new ObjectMapper(); + Map map = objectMapper.readValue(json, Map.class); + map.forEach((k, v) -> { + if (v instanceof String) { + v = cleanXSS((String) v); + map.put(k, v); + } + }); + json = objectMapper.writeValueAsString(map); + requestBody = json.getBytes(); + } + } + + /** + * Handles arguments annotated by @RequestBody + * + * @return + * @throws IOException + */ + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } + + /** + * Handles arguments annotated by @RequestParam + * + * @param name + * @return + */ + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (values != null && values.length > 0) { + String[] safeValues = new String[values.length]; + for (int i = 0; i < values.length; i++) { + safeValues[i] = cleanXSS(values[i]); + } + return safeValues; + } + return values; + } + + /** + * Handles arguments annotated by @PathVariable + * + * @param name + * @return + */ + @Override + public Object getAttribute(String name) { + Object value = super.getAttribute(name); + if (name.equalsIgnoreCase(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) && value != null && value instanceof Map) { + ((Map) value).forEach((k, v) -> { + if (v instanceof String) { + v = cleanXSS((String) v); + ((Map) value).put(k, v); + } + }); + } + return value; + } + + /** + * Handles arguments annotated by @RequestHeader + * + * @param name + * @return + */ + @Override + public Enumeration getHeaders(String name) { + List list = Collections.list(super.getHeaders(name)); + list = list.stream().map((e) -> { + ObjectMapper objectMapper = new ObjectMapper(); + try { + Map map = objectMapper.readValue(e, Map.class); + map.forEach((k, v) -> { + v = cleanXSS(v); + map.put(k, v); + }); + e = objectMapper.writeValueAsString(map); + } catch (JsonProcessingException e1) { + e1.printStackTrace(); + } + return e; + }).collect(Collectors.toList()); + return Collections.enumeration(list); + } + + @Override + public String getParameter(String name) { + String value = super.getParameter(name); + if (value != null) { + value = cleanXSS(value); + } + return value; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + /** + * Escape string to defend against XSS + * + * @param value + */ + private String cleanXSS(String value) { + value = StringEscapeUtils.escapeHtml(value); + return value; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java new file mode 100644 index 000000000..7d8e7ecba --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java @@ -0,0 +1,23 @@ +package com.tencent.cloud.polaris.router.example.xss; + +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * filter request aim at defending against XSS + * + * @author Daifu Wu + */ +@WebFilter(urlPatterns = "/*", filterName = "xssFilter") +@Component +public class XssFilter implements Filter { + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + filterChain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..3df2fe834 --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java @@ -0,0 +1,144 @@ +package com.tencent.cloud.polaris.router.example.xss; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.web.servlet.HandlerMapping; +import org.springframework.web.util.HtmlUtils; +import org.springframework.web.util.JavaScriptUtils; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +/** + * Wrap HttpServletRequest to escape String arguments + * + * @author Daifu Wu + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private byte[] requestBody; + + public XssHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + BufferedReader reader = request.getReader(); + StringBuilder stringBuilder = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + String json = stringBuilder.toString(); + ObjectMapper objectMapper = new ObjectMapper(); + Map map = objectMapper.readValue(json, Map.class); + map.forEach((k, v) -> { + if (v instanceof String) { + v = cleanXSS((String) v); + map.put(k, v); + } + }); + json = objectMapper.writeValueAsString(map); + requestBody = json.getBytes(); + } + + /** + * Handles arguments annotated by @RequestBody + * + * @return + * @throws IOException + */ + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } + + /** + * Handles arguments annotated by @RequestParam + * + * @param name + * @return + */ + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (values != null && values.length > 0) { + String[] safeValues = new String[values.length]; + for (int i = 0; i < values.length; i++) { + safeValues[i] = cleanXSS(values[i]); + } + return safeValues; + } + return values; + } + + /** + * Handles arguments annotated by @PathVariable + * + * @param name + * @return + */ + @Override + public Object getAttribute(String name) { + Object value = super.getAttribute(name); + if (name.equalsIgnoreCase(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) && value != null && value instanceof Map) { + ((Map) value).forEach((k, v) -> { + if (v instanceof String) { + v = cleanXSS((String) v); + ((Map) value).put(k, v); + } + }); + } + return value; + } + + @Override + public String getParameter(String name) { + String value = super.getParameter(name); + if (value != null) { + value = cleanXSS(value); + } + return value; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + /** + * Escape string to defend against XSS + * + * @param value + */ + private String cleanXSS(String value) { + value = StringEscapeUtils.escapeHtml(value); + return value; + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java new file mode 100644 index 000000000..7d8e7ecba --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java @@ -0,0 +1,23 @@ +package com.tencent.cloud.polaris.router.example.xss; + +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * filter request aim at defending against XSS + * + * @author Daifu Wu + */ +@WebFilter(urlPatterns = "/*", filterName = "xssFilter") +@Component +public class XssFilter implements Filter { + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + filterChain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse); + } +} diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..25ba7055b --- /dev/null +++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java @@ -0,0 +1,140 @@ +package com.tencent.cloud.polaris.router.example.xss; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.lang.StringEscapeUtils; +import org.springframework.web.servlet.HandlerMapping; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Map; + +/** + * Wrap HttpServletRequest to escape String arguments + * + * @author Daifu Wu + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private byte[] requestBody; + + public XssHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + BufferedReader reader = request.getReader(); + StringBuilder stringBuilder = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + stringBuilder.append(line); + } + String json = stringBuilder.toString(); + ObjectMapper objectMapper = new ObjectMapper(); + Map map = objectMapper.readValue(json, Map.class); + map.forEach((k, v) -> { + if (v instanceof String) { + v = cleanXSS((String) v); + map.put(k, v); + } + }); + json = objectMapper.writeValueAsString(map); + requestBody = json.getBytes(); + } + + /** + * Handles arguments annotated by @RequestBody + * + * @return + * @throws IOException + */ + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } + + /** + * Handles arguments annotated by @RequestParam + * + * @param name + * @return + */ + @Override + public String[] getParameterValues(String name) { + String[] values = super.getParameterValues(name); + if (values != null && values.length > 0) { + String[] safeValues = new String[values.length]; + for (int i = 0; i < values.length; i++) { + safeValues[i] = cleanXSS(values[i]); + } + return safeValues; + } + return values; + } + + /** + * Handles arguments annotated by @PathVariable + * + * @param name + * @return + */ + @Override + public Object getAttribute(String name) { + Object value = super.getAttribute(name); + if (name.equalsIgnoreCase(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE) && value != null && value instanceof Map) { + ((Map) value).forEach((k, v) -> { + if (v instanceof String) { + v = cleanXSS((String) v); + ((Map) value).put(k, v); + } + }); + } + return value; + } + + @Override + public String getParameter(String name) { + String value = super.getParameter(name); + if (value != null) { + value = cleanXSS(value); + } + return value; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(getInputStream())); + } + + /** + * Escape string to defend against XSS + * + * @param value + */ + private String cleanXSS(String value) { + value = StringEscapeUtils.escapeHtml(value); + return value; + } +} From f7492f0ac1b5792d366a84cd37ef98e887fb1d16 Mon Sep 17 00:00:00 2001 From: pandaapo <1052156701@qq.com> Date: Mon, 1 Aug 2022 22:48:40 +0800 Subject: [PATCH 2/2] Add copyright holder at the beginning of new .class file. Add information of this PR to CHANGELOG.md in root of project. --- changes/changes-1.6.0.md | 1 + .../example/xss/XssResponseBodyAdvice.java | 18 ++++++++++++++++++ .../gateway/example/callee/xss/XssFilter.java | 18 ++++++++++++++++++ .../xss/XssHttpServletRequestWrapper.java | 18 ++++++++++++++++++ .../gateway/example/callee/xss/XssFilter.java | 18 ++++++++++++++++++ .../xss/XssHttpServletRequestWrapper.java | 18 ++++++++++++++++++ .../polaris/router/example/xss/XssFilter.java | 18 ++++++++++++++++++ .../xss/XssHttpServletRequestWrapper.java | 18 ++++++++++++++++++ .../polaris/router/example/xss/XssFilter.java | 18 ++++++++++++++++++ .../xss/XssHttpServletRequestWrapper.java | 18 ++++++++++++++++++ 10 files changed, 163 insertions(+) diff --git a/changes/changes-1.6.0.md b/changes/changes-1.6.0.md index 819415784..e9be74806 100644 --- a/changes/changes-1.6.0.md +++ b/changes/changes-1.6.0.md @@ -40,3 +40,4 @@ - [Optimize starters auto-configuration. (main)](https://github.com/Tencent/spring-cloud-tencent/pull/391/files) - [Feature: format code](https://github.com/Tencent/spring-cloud-tencent/pull/394) - [test: add PostInitPolarisSDKContextTest](https://github.com/Tencent/spring-cloud-tencent/pull/397) +- [Fix the code analysis error.](https://github.com/Tencent/spring-cloud-tencent/issues/462) \ No newline at end of file diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/xss/XssResponseBodyAdvice.java b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/xss/XssResponseBodyAdvice.java index ffd17754a..0c9850be6 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/xss/XssResponseBodyAdvice.java +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-example-a/src/main/java/com/tencent/cloud/polaris/circuitbreaker/example/xss/XssResponseBodyAdvice.java @@ -1,3 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + package com.tencent.cloud.polaris.circuitbreaker.example.xss; import org.apache.commons.lang.StringEscapeUtils; diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java index 3735059cd..114d352a3 100644 --- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java @@ -1,3 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + package com.tencent.cloud.polaris.gateway.example.callee.xss; import org.springframework.stereotype.Component; diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java index 60f2c28f8..9e23f8c2b 100644 --- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java @@ -1,3 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + package com.tencent.cloud.polaris.gateway.example.callee.xss; import com.fasterxml.jackson.core.JsonProcessingException; diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java index 3735059cd..114d352a3 100644 --- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssFilter.java @@ -1,3 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + package com.tencent.cloud.polaris.gateway.example.callee.xss; import org.springframework.stereotype.Component; diff --git a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java index 6b51a2978..1830ea5b8 100644 --- a/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java +++ b/spring-cloud-tencent-examples/polaris-gateway-example/gateway-callee-service2/src/main/java/com/tencent/cloud/polaris/gateway/example/callee/xss/XssHttpServletRequestWrapper.java @@ -1,3 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + package com.tencent.cloud.polaris.gateway.example.callee.xss; import com.fasterxml.jackson.core.JsonProcessingException; diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java index 7d8e7ecba..0f72c82d9 100644 --- a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java +++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java @@ -1,3 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + package com.tencent.cloud.polaris.router.example.xss; import org.springframework.stereotype.Component; diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java index 3df2fe834..99b38c726 100644 --- a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java +++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service1/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java @@ -1,3 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + package com.tencent.cloud.polaris.router.example.xss; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java index 7d8e7ecba..0f72c82d9 100644 --- a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java +++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssFilter.java @@ -1,3 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + package com.tencent.cloud.polaris.router.example.xss; import org.springframework.stereotype.Component; diff --git a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java index 25ba7055b..03a63d05f 100644 --- a/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java +++ b/spring-cloud-tencent-examples/polaris-router-example/router-callee-service2/src/main/java/com/tencent/cloud/polaris/router/example/xss/XssHttpServletRequestWrapper.java @@ -1,3 +1,21 @@ +/* + * Tencent is pleased to support the open source community by making Spring Cloud Tencent available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + */ + package com.tencent.cloud.polaris.router.example.xss; import com.fasterxml.jackson.databind.ObjectMapper;