SpringBoot 解决跨站脚本漏洞(XSS)问题

忘是亡心i 2024-03-16 22:47 117阅读 0赞

一、问题背景

使用 SpringBoot 的项目出现了跨站脚本漏洞(XSS)问题。

二、解决方案

步骤如下:

1、添加maven依赖

在 pom.xml 文件中,增加如下依赖:

  1. <dependency>
  2. <groupId>org.apache.tomcat</groupId>
  3. <artifactId>tomcat-servlet-api</artifactId>
  4. <version>8.0.36</version>
  5. <scope>provided</scope>
  6. </dependency>
  7. <dependency>
  8. <groupId>javax.servlet</groupId>
  9. <artifactId>servlet-api</artifactId>
  10. <version>2.5</version>
  11. <scope>provided</scope>
  12. </dependency>
2、新增 XSSFilter.java

config 目录下增加 XSSFilter.java,用于对请求接口进行过滤。
代码如下:

  1. import javax.servlet.*;
  2. import javax.servlet.annotation.WebFilter;
  3. import javax.servlet.http.HttpServletRequest;
  4. import java.io.IOException;
  5. @WebFilter(filterName="XSSFilter", urlPatterns="/*")
  6. public class XSSFilter implements Filter {
  7. FilterConfig filterConfig = null;
  8. @Override
  9. public void init(FilterConfig filterConfig) throws ServletException {
  10. this.filterConfig = filterConfig;
  11. }
  12. @Override
  13. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  14. filterChain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
  15. }
  16. @Override
  17. public void destroy() {
  18. this.filterConfig = null;
  19. }
  20. }
3、新增 XssHttpServletRequestWrapper.java

config 目录下,新增 XssHttpServletRequestWrapper.java,用于对请求参数进行预处理和解析。
代码如下:

  1. import javax.servlet.ReadListener;
  2. import javax.servlet.ServletInputStream;
  3. import javax.servlet.http.HttpServletRequest;
  4. import javax.servlet.http.HttpServletRequestWrapper;
  5. import java.io.BufferedReader;
  6. import java.io.ByteArrayInputStream;
  7. import java.io.IOException;
  8. import java.io.InputStreamReader;
  9. import java.nio.charset.Charset;
  10. import java.util.HashMap;
  11. import java.util.Map;
  12. public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
  13. public XssHttpServletRequestWrapper(HttpServletRequest request) {
  14. super(request);
  15. }
  16. @Override
  17. public String[] getParameterValues(String parameter) {
  18. String[] values = super.getParameterValues(parameter);
  19. if (values==null) {
  20. return null;
  21. }
  22. int count = values.length;
  23. String[] encodedValues = new String[count];
  24. for (int i = 0; i < count; i++) {
  25. encodedValues[i] = cleanXSS(values[i]);
  26. }
  27. return encodedValues;
  28. }
  29. @Override
  30. public String getParameter(String parameter) {
  31. String value = super.getParameter(parameter);
  32. if (value != null) {
  33. return cleanXSS(value);
  34. }
  35. return null;
  36. }
  37. /**
  38. * 对 application/x-www-form-urlencoded 格式的POST请求参数,进行 cleanXSS解析
  39. * @return cleanXSS解析后的参数
  40. */
  41. @Override
  42. public Map<String, String[]> getParameterMap() {
  43. Map<String, String[]> values = super.getParameterMap();
  44. if (values == null) {
  45. return null;
  46. }
  47. Map<String, String[]> result = new HashMap<>();
  48. for (String key : values.keySet()) {
  49. String encodedKey = cleanXSS(key);
  50. int count = values.get(key).length;
  51. String[] encodedValues = new String[count];
  52. for (int i = 0; i < count; i++) {
  53. encodedValues[i] = cleanXSS(values.get(key)[i]);
  54. }
  55. result.put(encodedKey, encodedValues);
  56. }
  57. return result;
  58. }
  59. @Override
  60. public String getHeader(String name) {
  61. String value = super.getHeader(name);
  62. if (value == null)
  63. return null;
  64. return cleanXSS(value);
  65. }
  66. private static String cleanXSS(String value) {
  67. value = value.replaceAll("<", "<").replaceAll(">", ">");
  68. value = value.replaceAll("%3C", "<").replaceAll("%3E", ">");
  69. value = value.replaceAll("\\(", "(").replaceAll("\\)", ")");
  70. value = value.replaceAll("%28", "(").replaceAll("%29", ")");
  71. value = value.replaceAll("'", "'");
  72. value = value.replaceAll("eval\\((.*)\\)", "");
  73. value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
  74. value = value.replaceAll("script", "");
  75. return value;
  76. }
  77. @Override
  78. public ServletInputStream getInputStream() throws IOException {
  79. final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream ()).getBytes ());
  80. return new ServletInputStream() {
  81. @Override
  82. public int read() throws IOException {
  83. return bais.read();
  84. }
  85. @Override
  86. public boolean isFinished() {
  87. return false;
  88. }
  89. @Override
  90. public boolean isReady() {
  91. return false;
  92. }
  93. @Override
  94. public void setReadListener(ReadListener readListener) {
  95. }
  96. };
  97. }
  98. public String inputHandlers(ServletInputStream servletInputStream){
  99. StringBuilder sb = new StringBuilder();
  100. BufferedReader reader = null;
  101. try {
  102. reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));
  103. String line = "";
  104. while ((line = reader.readLine()) != null) {
  105. sb.append(line);
  106. }
  107. } catch (IOException e) {
  108. e.printStackTrace();
  109. } finally {
  110. if (servletInputStream != null) {
  111. try {
  112. servletInputStream.close();
  113. } catch (IOException e) {
  114. e.printStackTrace();
  115. }
  116. }
  117. if (reader != null) {
  118. try {
  119. reader.close();
  120. } catch (IOException e) {
  121. e.printStackTrace();
  122. }
  123. }
  124. }
  125. return cleanXSS(sb.toString ());
  126. }
  127. }
4、添加注解 @ServletComponentScan

XXXApplication.java 的类名上方,用于扫描配置类。添加注解如下:

  1. @ServletComponentScan("com.XXX.config")

示例如下:
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,117人围观)

还没有评论,来说两句吧...

相关阅读

    相关 xss脚本

    原理 跨站脚本(Cross site script,简称xss)是一种“HTML注入”,由于攻击的脚本多数时候是跨域的,所以称之为“跨域脚本”。 我们常常听到“注入”(I