java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > springboot解决XSS存储型漏洞

springboot解决XSS存储型漏洞问题

作者:黎明晓月

这篇文章主要介绍了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存储型漏洞应该就能解决了

总结

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

您可能感兴趣的文章:
阅读全文