springboot项目如何防止XSS攻击

目录
  • 1. 什么是XSS攻击?
  • 2. 如何防范?
    • 2.1 什么时候注入请求参数
  • 3. 具体处理细节

1. 什么是XSS攻击?

XSS攻击全称跨站脚本攻击,是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。也就是作恶的用户通过表单提交一些前端代码,如果不做处理的话,这些前端代码将会在展示的时候被浏览器执行。

2. 如何防范?

有两种方式,一种是一些特殊字符转义,另一种是去除一些危险html元素。本文通过JSOUP库实现第二种方式。

现在问题是,在什么时候对XSS攻击的字符串进行处理呢?这就涉及到spring mvc的Controller中的method params什么时候注入的问题。下面对方法参数注入的原理进行简单说明。

2.1 什么时候注入请求参数

常见的控制器方法有下面几种,分别是通过GET获取请求参数,POST获取json或者form表单的参数

        /**
         * 通过url的path,获取请求参数
         */
        @ResponseBody
        @GetMapping("/xssByGetUsingPath/{content}")
        public String testGetUsingPath(@PathVariable(name = "content") String content) {
            return content;
        }       

         /**
         * 通过url的query params获取请求数据. 方法使用简单类型进行接收
         */
        @ResponseBody
        @GetMapping("/xssByGetUsingSimple")
        public String testUsingSimple(@RequestParam(name = "content") String content) {
            return content;
        }

        /**
         * 通过url的query params获取请求数据. 方法使用model进行接收
         */
        @ResponseBody
        @GetMapping("/xssByGetUsingModel")
        public String testGetUsingModel(BaseTest.Paper paper) {
            return paper.getContent();
        }

        /**
         * 通过 form 表单的方式获取数据. 方法使用简单类型进行接收
         */
        @ResponseBody
        @PostMapping("/xssByFormPostUsingSimple")
        public String testFormPostUsingSimple(@RequestParam(name = "content") String content) {
            return content;
        }

        /**
         * 通过 form 表单的方式获取数据. 方法使用model进行参数接收
         */
        @ResponseBody
        @PostMapping("/xssByFormPostUsingModel")
        public String testFormPostUsingModel(BaseTest.Paper paper) {
            return paper.getContent();
        }

        /**
         * 通过 request body 发送 json数据
         */
        @ResponseBody
        @PostMapping("/xssByPostJsonBody")
        public String testPostJsonBody(@RequestBody BaseTest.Paper paper) {
            return paper.getContent();
        }

大家都知道,在spring mvc中处理请求的入口在 DispatcherServlet 类中,其中 doDispatch() 方法完成所有核心功能。在该主流程中,HandlerAdapter 将会对HTTP请求进行 Controller 的方法调用,以及对请求结果进行转换,并封装为DispatcherServlet 类需要的 ModelAndView 。在这里,由于使用注解的方式进行 Controller 定义,所以 HandlerAdapter 的实现类为 RequestMappingHandlerAdapter 。RequestMappingHandlerAdapter 类的 handle() 方法中,委托给 HandlerMethodArgumentResolver 对每个 Controller 的 方法的每个参数进行解析,反射调用 Controller 的 方法后,再 委托 HandlerMethodReturnValueHandler 对反射调用的返回值进行处理。

至此,本文的主角出现了,也就是 HandlerMethodArgumentResolver 。我们看下有关于本文的HandlerMethodArgumentResolver 类继承关系。

上面的常见controller定义方法的 参数解析(注意,这里是说方法那里的参数解析) 对应 HandlerMethodArgumentResolver  的关系如下图:

现在,我们已经知道了他们都由什么样 HandlerMethodArgumentResolver  解析方法参数,我们继续分析他们之前的共同点,并得到在哪里对http传过来的数据进行XSS处理。

RequestResponseBodyMethodProcessor 是一个对request body的JSON数据反序列化的处理器,在 resolveArgument() 方法中,将会获取合适的 org.springframework.http.converter.HttpMessageConverter  类对string数据进行反序列化处理。springboot 在初始化的时候,已经默认注册了 jackson 的 MappingJackson2HttpMessageConverter ,并使用它对 JSON 数据进行反序列化操作。在 jackson 里面,JsonDeserializer 类 用于json数据的property的反序列化,因此,我们可以通过扩展 JsonDeserializer ,并在里面处理XSS即可。

对于  PathVariableMethodArgumentResolver、 RequestParamMethodArgumentResolver、 ServletModelAttributeMethodProcessor ,在 resolveArgument() 方法中,他们对需要对请求参数调用 DataBinder 类 对获取到的参数类型转换和数据绑定。对于类型转换的过程,他们会使用 org.springframework.core.convert.converter.Converter  进行转换。同样,在SPRINGBOOT初始化的过程,也注册了很多个默认的转换器,我们可以注册一个自定义转换器,用于对数据进行xss处理。

3. 具体处理细节

抽象XSSCleaner,用于对string进行XSS处理

public interface XssCleaner {

    /**
     * 清理 html, 防止XSS
	 *
     * @param html html
     * @return 清理后的数据
     */
    String clean(String html);

}

使用JSOUP,做HTML节点的白名单处理

public class DefaultXssCleaner implements XssCleaner {

    public static final HtmlWhitelist WHITE_LIST = new HtmlWhitelist();

    @Override
    public String clean(String html) {
        if (StringUtils.hasText(html)) {
            return Jsoup.clean(html, WHITE_LIST);
        }
        return html;
    }

    private static class HtmlWhitelist extends Whitelist {

        public HtmlWhitelist() {
            //定义标签和属性的白名单

            addTags("a", "b", "blockquote", "br", "caption", "cite", "code", "col", "colgroup", "dd", "div", "span", "embed", "object", "dl", "dt",
                    "em", "h1", "h2", "h3", "h4", "h5", "h6", "i", "img", "li", "ol", "p", "pre", "q", "small",
                    "strike", "strong", "sub", "sup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "u", "ul");

            addAttributes("a", "href", "title", "target");
            addAttributes("blockquote", "cite");
            addAttributes("col", "span");
            addAttributes("colgroup", "span");
            addAttributes("img", "align", "alt", "src", "title");
            addAttributes("ol", "start");
            addAttributes("q", "cite");
            addAttributes("table", "summary");
            addAttributes("td", "abbr", "axis", "colspan", "rowspan", "width");
            addAttributes("th", "abbr", "axis", "colspan", "rowspan", "scope", "width");
            addAttributes("video", "src", "autoplay", "controls", "loop", "muted", "poster", "preload");
            addAttributes("object", "width", "height", "classid", "codebase");
            addAttributes("param", "name", "value");
            addAttributes("embed", "src", "quality", "width", "height", "allowFullScreen", "allowScriptAccess", "flashvars", "name", "type", "pluginspage");

            addAttributes(":all", "class", "style", "height", "width", "type", "id", "name");

            addProtocols("blockquote", "cite", "http", "https");
            addProtocols("cite", "cite", "http", "https");
            addProtocols("q", "cite", "http", "https");

        }

        @Override
        protected boolean isSafeAttribute(String tagName, Element el, Attribute attr) {
            //不允许 javascript 开头的 src 和 href
            if ("src".equalsIgnoreCase(attr.getKey()) || "href".equalsIgnoreCase(attr.getKey())) {
                String value = attr.getValue();
                if (StringUtils.hasText(value) && value.toLowerCase().startsWith("javascript")) {
                    return false;
                }
            }

            //允许 base64 的图片内容
            if ("img".equals(tagName) && "src".equals(attr.getKey()) && attr.getValue().startsWith("data:;base64")) {
                return true;
            }

            return super.isSafeAttribute(tagName, el, attr);
        }
    }
}

新增一个jackson的JsonDeserializer

/**
 * jackson的反序列化时的html xss过滤器
 */
public class JacksonXssCleanJsonDeserializer extends JsonDeserializer<String> {

    private final static Logger LOGGER = LoggerFactory.getLogger(JacksonXssCleanJsonDeserializer.class);

    private final XssCleaner xssCleaner;

    public JacksonXssCleanJsonDeserializer(XssCleaner xssCleaner) {
        this.xssCleaner = xssCleaner;
    }

    @Override
    public Class<?> handledType() {
        return String.class;
    }

    @Override
    public String deserialize(JsonParser p, DeserializationContext context) throws IOException, JsonProcessingException {
        // XSS clean
        String text = p.getValueAsString();
        if (StringUtils.hasText(text) && XssCleanMarker.shouldClean()) {
            String cleanText = xssCleaner.clean(text);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Json property value: [{}] cleaned up by JacksonXssCleanJsonDeserializer, current value is:{}.", text, cleanText);
            }
            return cleanText;
        }
        return text;
    }
}

新增 Converter

/**
 * 对请求数据过滤xss
 */
public class XssCleanConverter implements Converter<String, String> {

    private final Logger LOGGER = LoggerFactory.getLogger(XssCleanConverter.class);

    private XssCleaner xssCleaner;

    public XssCleanConverter(XssCleaner xssCleaner) {
        this.xssCleaner = xssCleaner;
    }

    @Override
    public String convert(String text) {
        if (StringUtils.hasText(text) && XssCleanMarker.shouldClean()) {
            String cleanText = xssCleaner.clean(text);
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("request param [{}] cleaned up by XssCleanConverter, current value is:{}.", text, cleanText);
            }
            return cleanText;
        }
        return text;
    }
}

对 JsonDeserializer  和 Converter 进行注册

@Configuration
@ConditionalOnProperty(value = XSS_PROPERTIES_ENABLED, havingValue = "true", matchIfMissing = true)
@ConditionalOnWebApplication
@EnableConfigurationProperties({XssProperties.class})
public class WebXssConfiguration implements WebMvcConfigurer {

    private XssProperties properties;

    public WebXssConfiguration(XssProperties properties) {
        this.properties = properties;
    }

    @Bean
    @ConditionalOnMissingBean
    public XssCleaner xssCleaner() {
        return new DefaultXssCleaner();
    }

    @Bean
    @ConditionalOnClass(value = {ObjectMapper.class, Jackson2ObjectMapperBuilder.class})
    public Jackson2ObjectMapperBuilderCustomizer jacksonXssCleanJsonDeserializerCustomer(XssCleaner xssCleaner) {
        return builder -> builder.deserializers(new JacksonXssCleanJsonDeserializer(xssCleaner));
    }

    @Override
    public void addFormatters(FormatterRegistry registry) {
        XssCleaner xssCleaner = xssCleaner();
        registry.addConverter(new XssCleanConverter(xssCleaner));
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        XssCleanMarkerHandlerInterceptor handlerInterceptor = new XssCleanMarkerHandlerInterceptor(properties);
        registry.addInterceptor(handlerInterceptor);
    }
}

上面是XSS处理的核心代码。处理XSS处理,还进行了一些扩展,比如 http path 路径的过滤 和 一些使能控制。

完整的代码可以参考仓库:仓库地址

以上就是springboot项目如何防止XSS攻击的详细内容,更多关于springboot防止XSS攻击的资料请关注我们其它相关文章!

(0)

相关推荐

  • springboot2.x使用Jsoup防XSS攻击的实现

    后端应用经常接收各种信息参数,例如评论,回复等文本内容.除了一些场景下面,可以特定接受的富文本标签和属性之外(如:b,ul,li,h1, h2, h3...),需要过滤掉危险的字符和标签,防止xss攻击. 一.什么是XSS? 看完这个,应该有一个大致的概念. XSS攻击常识及常见的XSS攻击脚本汇总 XSS过滤速查表 二.准则 永远不要相信用户的输入和请求的参数(包括文字.上传等一切内容) 参考第1条 三.实现做法 结合具体业务场景,对相应内容进行过滤,这里使用Jsoup. jsoup是一款Ja

  • SpringBoot如何防止XSS注入攻击详解

    什么是 XSS 攻击 在跨站脚本(XSS)攻击中,攻击者可以在受害者的浏览器中执行恶意脚本.这种攻击通常是通过在网页中插入恶意代码 (JavaScript) 来完成的.攻击者在使用攻击后一般能够: 修改网页内容 将用户重定向到其他网站 访问用户的 Cookie 并利用此信息来冒充用户 访问有关用户系统的关键信息,例如地理位置,网络摄像头,文件系统 将木马功能注入应用程序 如果被攻击的用户在应用程序中具有更高的权限.攻击者可以完全控制应用程序,并破坏所有用户及其数据. XSS 攻击类型 常见的 X

  • Springboot实现XSS漏洞过滤的示例代码

    背景 前阵子做了几个项目,终于开发完毕,进入了测试阶段,信心满满将项目部署到测试环境,然后做了安全测评之后..... ​(什么!你竟然说我代码不安全???) 然后测出了 Xss漏洞 安全的问题 解决方案 场景:可以在页面输入框输入JS脚本, 攻击者可以利用此漏洞执行恶意的代码 ! 问题演示 ​ ​ 所以我们要对于前端传输的参数做处理,做统一全局过滤处理 既然要过滤处理,我们首先需要实现一个自定义过滤器 总共包含以下四部分 XssUtil XssFilterAutoConfig XssHttpSe

  • springboot项目如何防止XSS攻击

    目录 1. 什么是XSS攻击? 2. 如何防范? 2.1 什么时候注入请求参数 3. 具体处理细节 1. 什么是XSS攻击? XSS攻击全称跨站脚本攻击,是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中.也就是作恶的用户通过表单提交一些前端代码,如果不做处理的话,这些前端代码将会在展示的时候被浏览器执行. 2. 如何防范? 有两种方式,一种是一些特殊字符转义,另一种是去除一些危险html元素.本文通过JSOUP库实现第二种方式. 现在问题是,在什么

  • 一次VUE项目中遇到XSS攻击的实战记录

    目录 前言 发现原因 自定义过滤规则 总结 前言 随着互联网的高速发展,信息安全问题已经成为企业最为关注的焦点之一,而前端又是引发企业安全问题的高危据点.在移动互联网时代,前端人员除了传统的 XSS.CSRF 等安全问题之外,又时常遭遇网络劫持.非法调用 Hybrid API 等新型安全问题.当然,浏览器自身也在不断在进化和发展,不断引入 CSP.Same-Site Cookies 等新技术来增强安全性,但是仍存在很多潜在的威胁,这需要前端技术人员不断进行"查漏补缺". 发现原因 一切

  • springboot清除字符串前后空格与防xss攻击方法

    目录 springboot清除字符串前后空格与防xss攻击 一.查看WebMvcAutoConfiguration.class中的方法源码 二.自定义属性编辑器 三.创建WebBindingInitializerConfiguration类 springboot去除参数中前后空格说明 一. 需求 二. 解决方法 三. 完美解决 springboot清除字符串前后空格与防xss攻击 一.查看WebMvcAutoConfiguration.class中的方法源码 protected Configur

  • Spring Boot项目抵御XSS攻击实战过程

    目录 前言 一.什么是XSS攻击 二.如何抵御XSS攻击 三.实现抵御XSS攻击 总结 前言 作为Web网站来说,抵御XSS攻击是必须要做的事情,这是非常常见的黑客攻击手段之一. 一.什么是XSS攻击 XSS意思是跨站脚本攻击,英文全称Cross Site Scripting,为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS. XSS攻击的手段很简单,就是通过各种手段向我们的Web网站植入JS代码.比如说普通网站的用户注册.论坛

  • SpringBoot2.x 整合 AntiSamy防御XSS攻击的简单总结

    AntiSamy是OWASP的一个开源项目,通过对用户输入的HTML.CSS.JavaScript等内容进行检验和清理,确保输入符合应用规范.AntiSamy被广泛应用于Web服务对存储型和反射型XSS的防御中. XSS攻击全称为跨站脚本攻击(Cross Site Scripting),是一种在web应用中的计算机安全漏洞,它允许用户将恶意代码(如script脚本)植入到Web页面中,为了不和层叠样式表(Cascading Style Sheets, CSS)混淆,一般缩写为XSS.XSS分为以

  • 浅谈Springboot2.0防止XSS攻击的几种方式

    目录 防止XSS攻击,一般有两种做法: 转义 做法的三种实现: 转义方法一:注册自定义转换器 转义方法二:BaseController 转义方法三:Converter 在平时做项目代码开发的时候,很容易忽视XSS攻击的防护,网上有很多自定义全局拦截器来实现XSS过滤,其实不需要这么麻烦,SpringBoot留有不少钩子(扩展点),据此我们可以巧妙地实现全局的XSS过滤 防止XSS攻击,一般有两种做法: 转义使用工具类HtmlUtils实现 过滤将敏感标签去除jsoup实现了非常强大的clean敏

  • Java防止xss攻击附相关文件下载

    跨站脚本(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种.它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响.这类攻击通常包含了HTML以及用户端脚本语言. XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序.这些恶意网页程序通常是JavaScript,但实际上也可以包括Java,VBScript,ActiveX,Flash或者甚至

  • java 最新Xss攻击与防护(全方位360°详解)

    前沿 XSS防范属于前端还是后端的责任 ? XSS 防范是后端 RD(研发人员)的责任,后端 RD 应该在所有用户提交数据的接口,对敏感字符进行转义,才能进行下一步操作. 所有要插入到页面上的数据,都要通过一个敏感字符过滤函数的转义,过滤掉通用的敏感字符后,就可以插入到页面中. 公司的搜索页面如果你是下面的写法.那么他可能存在Xss注入 <input type="text" value="<%= getParameter("keyword")

  • 详解java解决XSS攻击常用方法总结

    前言 在项目验收阶段,通常会对待验收项目做一些安全漏洞的测试,比如接口攻击,并发测试,XSS注入,SQL恶意注入测试,安全越权等操作,这时,就是考验项目的安全方面是否做的足够健壮的时候,本篇对XSS脚本攻击在实际WEB项目中的处理办法,提供2种可实行的方法 xss攻击 XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序.这些恶意网页程序通常是JavaScript,但实际上也可以包括Java. VBScript.Acti

随机推荐