springboot解决XSS存储型漏洞问题

 更新时间:2024年05月30日 11:01:13   作者:黎明晓月  
这篇文章主要介绍了springboot解决XSS存储型漏洞问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

XSS攻击

XSS 攻击

跨站脚本攻击(Cross Site Scripting),为不和 前端层叠样式表(Cascading Style Sheets)CSS 混淆,故将跨站脚本攻击缩写为 XSS。

XSS(跨站脚本攻击)

是指恶意攻击者往 Web 页面里插入恶意 Script 代码,当用户浏览该页时,嵌入其中 Web 里面的 Script 代码会被执行,从而达到恶意攻击用户的目的。

类似于 sql 注入。是目前最普遍的 Web 应用安全漏洞,也是 Web 攻击中最常见的攻击方式之一。

XSS( 跨站脚本攻击)攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。

这些恶意网页程序通常是 JavaScript,但实际上也可以包括 Java、 VBScript、ActiveX、 Flash 或者甚至是普通的 HTML。

攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和 cookie 等各种内容。

XSS攻击示例

过滤请求非法内容XSS类:XssRequestWrappers

这个类用来过滤请求非法内容,详细代码如下:

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

/**
 * @ClassName XssRequestWrappers
 * @Description TODO
 * @Author tongxueqiyue
 * @Date 2023/12/18 10:43
 * @Version 1.0
 */
public class XssRequestWrappers extends HttpServletRequestWrapper {
    private CommonsMultipartResolver multiparResolver = new CommonsMultipartResolver();

    public XssRequestWrappers(HttpServletRequest request) {
        super(request);

        String type = request.getHeader("Content-Type");
        if (!StringUtils.isEmpty(type) && type.contains("multipart/form-data")) {
            MultipartHttpServletRequest multipartHttpServletRequest = multiparResolver.resolveMultipart(request);
            Map<String, String[]> stringMap = multipartHttpServletRequest.getParameterMap();
            if (!stringMap.isEmpty()) {
                for (String key : stringMap.keySet()) {
                    String value = multipartHttpServletRequest.getParameter(key);
                    striptXSS(key);
                    striptXSS(value);
                }
            }
            super.setRequest(multipartHttpServletRequest);
        }
    }

    @Override
    public String[] getParameterValues(String parameter) {
        String[] values = super.getParameterValues(parameter);
        if (values == null) {
            return null;
        }
        int count = values.length;
        String[] encodedValues = new String[count];
        for (int i = 0; i < count; i++) {
            encodedValues[i] = striptXSS(values[i]);
        }
        return encodedValues;
    }

    @Override
    public String getParameter(String parameter) {
        String value = super.getParameter(parameter);
        return striptXSS(value);
    }

    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        return striptXSS(value);
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> map1 = super.getParameterMap();
        Map<String, String[]> escapseMap = new HashMap<String, String[]>();
        Set<String> keys = map1.keySet();
        for (String key : keys) {
            String[] valArr = map1.get(key);
            if (valArr != null && valArr.length > 0) {
                String[] escapseValArr = new String[valArr.length];
                for (int i = 0; i < valArr.length; i++) {
                    String escapseVal = striptXSS(valArr[i]);
                    escapseValArr[i] = escapseVal;
                }
                escapseMap.put(key, escapseValArr);
            }
        }

        return escapseMap;
    }

	//处理非法内容,如果有新的在此处增加即可
    public static String striptXSS(String value) {
        if (value != null) {
            // 替换空字符串,以便清除潜在的恶意脚本
            value = value.replaceAll("", "");

            // 移除<script>标签及其内容
            Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");

            // 移除带有src属性的标签,支持单引号和双引号包围的属性值
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");

            // 移除</script>标签
            scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");

            // 移除以<script...>开头的标签
            scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");

            // 移除eval()函数调用
            scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");

            // 移除expression()函数调用
            scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");

            // 移除以"javascript:"开头的字符串
            scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");

            // 移除以"vbscript:"开头的字符串
            scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");

            // 移除以"onload..."开头的字符串
            scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");

            // 移除包含任何<和>字符的字符串
            scriptPattern = Pattern.compile(".*<.*", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
        }

        // 返回处理后的字符串
        return value;
    }
}

定义过滤器监听XSSFilter 重写Filter

在这个过滤器中监听XSSFilter,使用上面写的XssRequestWrappers来处理请求中的非法内容

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName XSSFilter
 * @Description TODO
 * @Author tongxueqiyue
 * @Date 2023/12/18 10:45
 * @Version 1.0
 */
public class XSSFilter implements Filter {

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        chain.doFilter(new XssRequestWrappers((HttpServletRequest) request), response);

    }
}

注册这个XSSFilter为Bean

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebConfig {

    @Bean
    public FilterRegistrationBean<XSSFilter> xssFilterRegistrationBean() {
        FilterRegistrationBean<XSSFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new XSSFilter());
        registrationBean.addUrlPatterns("/*"); // 这里配置需要过滤的URL
        registrationBean.setName("xssFilter");
        registrationBean.setOrder(1); // 设置过滤器的执行顺序,数字越小越优先
        return registrationBean;
    }
}

执行这三步应该就可以了,不过启动可能会报错,如果报错添加以下依赖即可:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

到这里XSS存储型漏洞应该就能解决了

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Spring Boot 使用 Swagger 构建 RestAPI 接口文档

    Spring Boot 使用 Swagger 构建 RestAPI 接口文档

    这篇文章主要介绍了Spring Boot 使用 Swagger 构建 RestAPI 接口文档,帮助大家更好的理解和使用Spring Boot框架,感兴趣的朋友可以了解下
    2020-10-10
  • IDEA更改Terminal的方法步骤

    IDEA更改Terminal的方法步骤

    Windows上开发有时候cmd不支持bash命令,有些操作就会非常麻烦,本文主要介绍了IDEA更改Terminal的方法步骤,具有一定的参考价值,感兴趣的可以了解一下
    2023-09-09
  • java实现多线程的两种方式继承Thread类和实现Runnable接口的方法

    java实现多线程的两种方式继承Thread类和实现Runnable接口的方法

    下面小编就为大家带来一篇java实现多线程的两种方式继承Thread类和实现Runnable接口的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • 从零开始设计基于SpringBoot的Serverless(本地函数计算)引擎

    从零开始设计基于SpringBoot的Serverless(本地函数计算)引擎

    最近突然冒出一个想法:能不能用SpringBoot自己实现一个类似AWS Lambda或阿里云函数计算的执行引擎,所以下面我们就来看看如何从零开始设计一套基于SpringBoot的Serverless执行框架吧
    2025-07-07
  • Spring超出最大会话数(Max sessions limit reached: 10000)

    Spring超出最大会话数(Max sessions limit reached: 10000)

    在Spring系统中遇到的Maxsessionslimitreached:10000错误,该错误由于会话数超过默认限制10000而触发,下面就来介绍一下解决方法,感兴趣的可以了解一下
    2024-12-12
  • java语言基础之标识符和命名规则详解

    java语言基础之标识符和命名规则详解

    这篇文章主要给大家介绍了关于java语言基础之标识符和命名规则的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • 使用EasyPoi实现多Sheet页导出的示例代码

    使用EasyPoi实现多Sheet页导出的示例代码

    在项目开发中,我们常常会遇到导出多Sheet页的需求,本文降维打击介绍一下如何使用EasyPoi实现这一功能,文中的示例代码简洁易懂,有需要的可以参考下
    2025-03-03
  • Spring中的@RestControllerAdvice注解使用方法解析

    Spring中的@RestControllerAdvice注解使用方法解析

    这篇文章主要介绍了Spring中的@RestControllerAdvice注解使用方法解析,@RestControllerAdvice是Controller的增强 常用于全局异常的捕获处理 和请求参数的增强,需要的朋友可以参考下
    2024-01-01
  • Spring boot创建自定义starter的完整步骤

    Spring boot创建自定义starter的完整步骤

    这篇文章主要给大家介绍了关于Spring boot创建自定义starter的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • Java如何基于DOM解析xml文件

    Java如何基于DOM解析xml文件

    这篇文章主要介绍了Java如何基于DOM解析xml文件,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09

最新评论