开发者

SpringBoot利用filter实现xss防御功能

开发者 https://www.devze.com 2024-09-27 10:28 出处:网络 作者: HBLOG
目录1.什么是xss?XSS 分类存储型 XSS反射型 XSSDOM 型 XSSXSS 攻击的预防2.代码工程实验目标pom.XMLcontrollerfilterconfigapplication.yaml代码仓库3.测试使用postman测试1.什么是xss?
目录
  • 1.什么是xss?
    • XSS 分类
      • 存储型 XSS
      • 反射型 XSS
      • DOM 型 XSS
    • XSS 攻击的预防
    • 2.代码工程
      • 实验目标
        • pom.XML
          • controller
            • filter
              • config
                • application.yaml
                  • 代码仓库
                  • 3.测试
                    • 使用postman测试

                    1.什么是xss?

                    Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。 为了和 css 区分,这里把攻击的第一个字母改成了 X,于是叫做 XSS。 XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。 而由于直接在用户的终端执行,恶意代码能够直接获取用户的信息,或者利用这些信息冒充用户向网站发起攻击者定义的请求。 在部分情况下,由于输入的限制,注入的恶意脚本比较短。但可以通过引入外部的脚本,并由浏览器执行,来完成比较复杂的攻击策略。 这里有一个问题:用户是通过哪种方法“注入”恶意脚本的呢? 不仅仅是业务上的“用户的 UGC 内容”可以进行注入,包括 URL 上的参数等都可以是攻击的来源。在处理输入时,以下内容都不可信:

                    • 来自用户的 UGC 信息
                    • 来自第三方的链接
                    • URL 参数
                    • POST 参数
                    • Referer (可能来自不可信的来源)
                    • Cookie (可能来自其他子域注入)

                    XSS 分类

                    根据攻击的来源,XSS 攻击可分为存储型、反射型和 DOM 型三种。 |类型|存储区

                    |插入点

                    | |-|-| |存储型 XSS|后端数据库|html| |反射型 XSS|URL|HTML| |DOM 型 XSS|后端数据库/前端存储/URL|前端 JavaScript|

                    • 存储区:恶意代码存放的位置。
                    • 插入点:由谁取得恶意代码,并插入到网页上。

                    存储型 XSS

                    存储型 XSS 的攻击步骤:

                    • 攻击者将恶意代码提交到目标网站的数据库中。
                    • 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
                    • 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
                    • 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

                    这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。

                    反射型 XSS

                    反射型 XSS 的攻击步骤:

                    • 攻击者构造出特殊的 URL,其中包含恶意代码。
                    • 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
                    • 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
                    • 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

                    反射型 XSS 跟存储型 XSS 的区别是:存储型 XSS 的恶意代码存在数据库里,反射型 XSS 的恶意代码存在 URL 里。 反射型 XSS 漏洞常见于通过 URL 传递参数的功能,如网站搜索、跳转等。 由于需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击。 POST 的内容也可以触发反射型 XSS,只不过其触发条件比较苛刻(需要构造表单提交页面,并引导用户点击),所以非常少见。

                    DOM 型 XSS

                    DOM 型 XSS 的攻击步骤:

                    • 攻击者构造出特殊的 URL,其中包含恶意代码。
                    • 用户打开带有恶意代码的 URL。
                    • 用户浏览器接收到响应后解析执行,前端 javascript 取出 URL 中的恶意代码并执行。
                    • 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

                    DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。

                    XSS 攻击的预防

                    通过前面的介绍可以得知,XSS 攻击有两大要素:

                    • 攻击者提交恶意代码。
                    • 浏览器执行恶意代码。

                    我们是否能够在用户输入的过程,过滤掉用户输入的恶意代码呢?

                    • 输入过滤
                    • 预防存储型和反射型 XSS 攻击
                    • 纯前端渲染
                    • 转义 HTML
                    • 预防 DOM 型 XSS 攻击

                    2.代码工程

                    实验目标

                    利用过滤器实现xss拦截

                    pom.xml

                    <?xml version="1.0" encoding="UTF-8"?>
                    <project xmlns="http://maven.apache.org/POM/4.0.0"
                             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
                        <parent>
                            <artifactId>springboot-demo</artifactId>
                            <groupId>com.et</groupId>
                            <version>1.0-SNAPSHOT</version>
                        </parent>
                        <modelVersion>4.0.0</modelVersion>
                    
                        <artifactId>xss</artifactId>
                    
                        <properties>
                            <maven.compiler.source>8</maven.compiler.source>
                            <maven.compiler.target>8</maven.compiler.target>
                        </properties>
                        <dependencies>
                            <dependency>
                                <groupId>org.springframework.boot</groupId>
                                <artifactId>spring-boot-starter-web</artifactId>
                            </dependency>
                    
                            <dependency>
                                <groupId>org.springframework.boot</groupId>
                                <artifactId>spring-boot-autoconfigure</artifactId>
                            </dependency>
                            <dependency>
                                <groupId>org.springframework.boot</groupId>
                                <artifactId>spring-boot-starter-test</artifactId>
                                <scope>test</scope>
                            </dependency>
                            <dependency>
                                <groupId>org.apache.commons&lhttp://www.devze.comt;/groupId>
                                <artifactId>commons-lang3</artifactId>
                            </dependency>
                            <dependency>
                                <groupId>org.jsoup</groupId>
                                <artifactId>jsoup</artifactId>
                                <version>1.11.3</version>
                            </dependency>
                        </dependencies>
                    </project>
                    

                    controller

                    package com.et.controller;
                    
                    import org.springframework.web.bind.annotation.RequestMapping;
                    import org.springframework.web.bind.annotation.RestController;
                    
                    import java.util.HashMap;
                    import java.util.Map;
                    
                    @RestController
                    public class HelloWorldController {
                        @RequestMapping("/hello")
                        public Map<String, Object> showHelloWorld(){
                            Map<String, Object> map = new HashMap<>();
                            map.put("msg", "HelloWorld");
                            return map;
                        }
                        @RequestMapping("/api/xss")
                        public void xssApiTest(String name, String content) {
                            System.out.println("api->name:"+name);
                            System.out.println("api->candroidontent:"+content);
                        }
                        /**
                         * bu
                         * @param name
                         * @param content
                         */
                        @RequestMapping("/ui/xss")
                        public void xssUiTest(String name, String content) {
                            System.out.println("ui->name:"+name);
                            System.out.println("ui->content:"+content);
                        }
                    }
                    

                    filter

                    具体拦截起的业务逻辑,你可以把你需要的拦截逻辑写在这里

                    package com.et.filter;
                    
                    
                    import org.apache.commons.lang3.StringUtils;
                    
                    import javax.servlet.*;
                    import javax.servlet.http.HttpServletRequest;
                    import javax.servlet.http.HttpServletResponse;
                    import java.io.IOException;
                    import java.util.ArrayList;
                    import java.util.List;
                    import java.util.regex.Matcher;
                    import java.util.regex.Pattern;
                    
                    /**
                     * 
                     * @author Frank
                     *
                     */
                    public class XssFilter implements Filter {
                        /**
                         * excludes  link
                         */
                       List<String> excludes = new ArrayList<String>();
                        /**
                         * xss filter switch
                         */
                        public boolean enabled = false;
                        @Override
                        public void init(FilterConfig filterConfig) throws ServletException {
                            String tempExcludes = filterConfig.getInitParameter("excludes");
                            String tempEnabled = filterConfig.getInitParameter("enabled");
                            if (StringUtils.isNotEmpty(tempExcludes)) {
                                String[] url = tempExcludes.split(",");
                                for (int i = 0; url != null && i < url.length; i++) {
                                    excludes.add(url[i]);
                                }
                            }
                            if (StringUtils.isNotEmpty(tempEnabled)) {
                                enabled = Boolean.valueOf(tempEnabled);
                            }
                        }
                        @Override
                        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                                throws IOException, ServletException {
                            HttpServletRequest req = (HttpServletRequest) request;
                            HttpServletResponse resp = (HttpServletResponse) response;
                            if (handleExcludeURL(req, resp)) {
                                chain.doFilter(request, response);
                                return;
                            }
                            XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
                            chain.doFilter(xssRequest, response);
                        }
                        private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
                            if (!enabled) {
                                return true;
                            }
                            if (excludes == null || excludes.isEmpty()) {
                                return false;
                            }
                            String url = request.getServletPath();
                            for (String pattern : excludes) {
                                Pattern p = Pattern.compile("^" + pattern);
                                Matcher m = p.matcher(url);
                                if (m.find()) {
                                    return true;
                                }
                            }
                            return false;
                        }
                        @Override
                        public void destroy() {
                        }
                    }
                    
                    package com.et.filter;
                    
                    import org.jsoup.Jsoup;
                    import org.jsoup.safety.Whitelist;
                    
                    import javax.servlet.http.HttpServletRequest;
                    import javax.servlet.http.HttpServletRequestWrapper;
                    
                    /**
                     * XSS filter process
                     * 
                     * @author Frank
                     *
                     */
                    public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
                        public XssHttpServletRequestWrapper(HttpServletRequest request) {
                            super(request);
                        }
                        @Override
                        public String[] getParameterValues(String name) {
                            // Customize rules based on actual needs. Here, the content field is rich text and does not need to be filtered.
                            if ("content".equals(name)) {
                                return super.getParameterValues(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++) {
                                    // Prevent xss attacks and filter leading and trailing spaces
                                    escapseValues[i] = Jsoup.clean(values[i], Whitelist.relaxed()).trim();
                                }
                                return escapseValues;
                            }
                            return super.getParameterValues(name);
                        }
                    }
                    

                    config

                    配置xss拦截过滤器,并注册到过滤链上

                    package com.et.编程config;
                    
                    import com.et.filter.XssFilter;
                    import org.springframework.beans.factory.annotation.Value;
                    import javax.servlet.DispatcherType;
                    import org.springframework.boot.web.servlet.FilterRegistrationBean;
                    import org.springframework.context.annotation.Bean;
                    import org.springframework.context.annotation.Configuration;
                    import org.springframework.util.StringUtils;
                    
                    import java.util.HashMap;
                    import java.util.Map;
                    
                    /**
                     * Filter config
                     * @author Frank
                     *
                     */
                    @Configurationphp
                    public class FilterConfig
                    {
                        @Value("${xss.enabled}")
                        private String enabled;
                        @Value("${xss.excludes}")
                        private String excludes;
                        @Value("${xss.urlPatterns}")
                        private String urlPatterns;
                        @SuppressWarnings({ "rawtypes", "unchecked" })
                        @Bean
                        public FilterRegistrationBean xssFilterRegistration()
                        {
                            FilterRegistrationBean registration = new FilterRegistrationBean();
                            registration.setDispatcherTypes(DispatcherType.REQUEST);
                            registration.setFilter(new XssFilter());
                            registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
                            registration.setName("xssFilter");
                            registration.setOrder(Integer.MAX_VALUE);
                            Map<String, String> initParameters = new HashMap<String, String>();
                            initParameters.put("excludes", excludes);
                            initParameters.put("enabled", enabled);
                            registration.setInitParameters(initParameters);
                            return registration;
                        }
                    }
                    

                    application.yaml

                    server:
                      port: 8088
                    
                    
                    xss:
                      enabled: true
                      #  Exclude links (separate multiple links with commas)
                      excludes: /ui/*
                      #  matc编程客栈h links (separate multiple links with commas)
                      urlPatterns: /api/*,/admin/*
                    

                    代码仓库

                    • https://github.com/Harries/springboot-demo(xss)

                    3.测试

                    启动Spring Boot应用程序

                    使用postman测试

                    SpringBoot利用filter实现xss防御功能

                    查看日志,发现name字段已经过滤了

                    SpringBoot利用filter实现xss防御功能

                    以上就是SpringBoot利用filter实现xss防御功能的详细内容,更多关于SpringBoot filter xss防御的资料请关注编程客栈(www.devze.com)其它相关文章!

                    0

                    精彩评论

                    暂无评论...
                    验证码 换一张
                    取 消

                    关注公众号