美文网首页
JeecgBoot抵御XSS攻击实现方案

JeecgBoot抵御XSS攻击实现方案

作者: JEECG | 来源:发表于2022-05-13 21:00 被阅读0次

    1. 问题描述

    jeecgboot后台启动后,在浏览器输入地址

    http://localhost:8080/jeecg-boot/jmreport/view/')%22οnmοuseοver=alert('hacking')%20%20(
    

    弹出对话框

    image.png

    2. 试验环境

    jeecgboot 3.0

    3. 增加配置类

    • 在jeecg-boot-module-system的config包下,新建xss包,并新增几个类


      image.png
    • 类的具体代码如下:

    package org.jeecg.config.xss;
     
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
     
    /**
     * Created by sunh on 2012/12/29.
     * xss 过滤器只能过滤form表单形式提交的参数
     */
    public class XssFilter implements Filter {
     
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
     
        }
     
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("***********开始过滤");
            XssHttpServletRequestWrapper xssRequest =
                    new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest);
            filterChain.doFilter(xssRequest, servletResponse);
        }
     
        @Override
        public void destroy() {
     
        }
    }
    
    package org.jeecg.config.xss;
     
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.module.SimpleModule;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
    import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
     
    /**
     * Created by sunh on 2012/12/29.
     * xss 自动配置类
     */
    @Configuration
    public class XssFilterAtuoConfig {
     
        @Bean
        public FilterRegistrationBean xssFiltrRegister() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new XssFilter());
            registration.addUrlPatterns("/*");
            registration.setName("XssFilter");
            registration.setOrder(1);
            return registration;
        }
     
     
        @Bean
        @Primary
        public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
            SimpleModule module = new SimpleModule();
            module.addDeserializer(String.class, new XssStringJsonDeserializer());
            ObjectMapper objectMapper = Jackson2ObjectMapperBuilder.json().build();
            objectMapper.registerModule(module);
            return new MappingJackson2HttpMessageConverter(objectMapper);
        }
    }
    
    package org.jeecg.config.xss;
     
    import org.springframework.web.servlet.HandlerMapping;
     
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.Objects;
     
    /**
     * Created by sunh on 2012/12/29.
     * xss 包装
     */
    public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
     
        public XssHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
        }
     
        @Override
        public String getHeader(String name) {
            String value = super.getHeader(name);
            return XssUtil.cleanXSS(value);
        }
     
        @Override
        public String getParameter(String name) {
            String value = super.getParameter(name);
            return XssUtil.cleanXSS(value);
        }
     
        @Override
        public String[] getParameterValues(String name) {
            String[] values = super.getParameterValues(name);
            if (values != null) {
                int length = values.length;
                String[] escapseValues = new String[length];
                for (int i = 0; i < length; i++) {
                    escapseValues[i] = XssUtil.cleanXSS(values[i]);
                }
                return escapseValues;
            }
            return super.getParameterValues(name);
        }
     
        /**
         * 主要是针对HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE 获取pathvalue的时候把原来的pathvalue经过xss过滤掉
         */
        @Override
        public Object getAttribute(String name) {
            // 获取pathvalue的值
            if (HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE.equals(name)) {
                Map uriTemplateVars = (Map) super.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
                if (Objects.isNull(uriTemplateVars)) {
                    return uriTemplateVars;
                }
                Map newMap = new LinkedHashMap<>();
                uriTemplateVars.forEach((key, value) -> {
                    if (value instanceof String) {
                        newMap.put(key, XssUtil.cleanXSS((String) value));
                    } else {
                        newMap.put(key, value);
     
                    }
                });
                return newMap;
            } else {
                return super.getAttribute(name);
            }
        }
    }
    
    package org.jeecg.config.xss;
     
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.module.SimpleModule;
     
    /**
     * Created by sunh on 2012/12/29.
     * 创建xss的json转换器
     */
    public class XssObjectMapper extends ObjectMapper {
     
        public XssObjectMapper() {
            SimpleModule module = new SimpleModule("XSS JsonDeserializer");
            module.addDeserializer(String.class, new XssStringJsonDeserializer());
            this.registerModule(module);
        }
    }
    
    package org.jeecg.config.xss;
     
    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.JsonDeserializer;
    import org.springframework.web.util.HtmlUtils;
     
    import java.io.IOException;
     
    /**
     * Created by sunh on 2012/12/29.
     * 基于xss的JsonDeserializer
     */
    public class XssStringJsonDeserializer extends JsonDeserializer<String> {
     
     
        @Override
        public Class<String> handledType() {
            return String.class;
        }
     
        @Override
        public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            return HtmlUtils.htmlEscape(jsonParser.getValueAsString());
        }
    }
    
    package org.jeecg.config.xss;
     
     
    import java.util.Objects;
     
    /**
     * Created by sunh on 2012/12/29
     * xss工具类
     */
    public class XssUtil {
     
        public static String cleanXSS(String value) {
            if (Objects.isNull(value)) {
                return value;
            }
            //You'll need to remove the spaces from the html entities below
            value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
            value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
            value = value.replaceAll("'", "& #39;");
            value = value.replaceAll("eval\\((.*)\\)", "");
            value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
            value = value.replaceAll("script", "");
            return value;
        }
    }
    

    4. 测试结果

    启动后端,在浏览器访问地址

    http://localhost:8080/jeecg-boot/jmreport/view/')%22οnmοuseοver=alert('hacking')%20%20(
    

    未弹出对话框

    image.png

    启动前端,原来的服务能正常访问。

    相关文章

      网友评论

          本文标题:JeecgBoot抵御XSS攻击实现方案

          本文链接:https://www.haomeiwen.com/subject/idpsurtx.html