SpringBoot过滤XSS脚本攻击

XSS攻击是什么

XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。

简而言之,就是作恶用户通过表单提交一些前端代码,如果不做处理的话,这些前端代码将会在展示的时候被浏览器执行。

如何避免XSS攻击

这里我根据个人经验做一个总结,可能经验也有不足之处。我个人解决XSS攻击是通过后端转译的办法来解决的。在实际项目中,react、vue等前后端完全分离的框架似乎已经帮我们处理了XSS脚本,这个本人对于前端略懂皮毛而已,这里就不做探讨了。下面主要实现以后端做XSS过滤。

代码实现

对于过滤XSS脚本的代码,通过搜索引擎可以搜索到很多,但似乎都不是那么全面。基本上都是只能过滤querystring类型的入参,而不能过滤json类型的入参。其实,在现在的开发中,更多的是使用json类型做数据交互。下面就直接贴代码了:

XssAndSqlHttpServletRequestWrapper.java

package com.loger.filter;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * @author wbs
 * 防止XSS攻击
 */
public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {

    private HttpServletRequest request;

    public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) {
        super(request);
        this.request = request;
    }

    @Override
    public String getParameter(String name) {
        String value = request.getParameter(name);
        if (!StringUtils.isEmpty(value)) {
            value = StringEscapeUtils.escapeHtml4(value);
        }
        return value;
    }

    @Override
    public String[] getParameterValues(String name) {
        String[] parameterValues = super.getParameterValues(name);
        if (parameterValues == null) {
            return null;
        }
        for (int i = 0; i < parameterValues.length; i++) {
            String value = parameterValues[i];      //这个过滤xss攻击的工具类,现在是借助第三方插件使用的。 也可以自己写一个工具类 比如下面的 XssUtil
      parameterValues[i] = StringEscapeUtils.escapeHtml4(value);      //自定义工具类      //parameterValues[i] = XssUtil.xssEncode(parameterValues[i]);
     } return parameterValues; } } 

简单讲解下,这里重写了两个方法:getParameter和getParameterValues,getParameter方法是直接通过request获得querystring类型的入参调用的方法。如果是通过springMVC注解类型来获得参数的话,走的是getParameterValues的方法。

StringEscapeUtils.escapeHtml4这个方法来自Apache的工具类,maven坐标如下:

<dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-text</artifactId>
      <version>1.4</version>
</dependency>

 //如果使用的是上面黄色的自定义工具类,来过滤xss 关键字,就需要导入下面XssUtils工具类,如果不使用的话下面这个工具类,就直接跳过不需要管。 但是有些人说为啥有第三方工具类,还要使用自定义工具类呢,应为使用第三方插件时,进行代码扫描时(我们公司项目上线需要进行代码扫描)会有问题(这个问题不影响代码使用),所以我用的是自定义类。总之这两种 工具类都可以用,不影响功能的实现。
/** * @Author wbs * @Description Web防火墙工具类 */public class XssUtil {

public static final String REPLACE_STRING = "*";

private XssUtil() {    }

/**     * xss校验     * @param s     * @return     */    public static String xssEncode(String s) {        if (StringUtils.isEmpty(s)) {            return s;        } else {            s = stripXSSAndSql(s);        }        StringBuilder sb = new StringBuilder(s.length() + 16);        for (int i = 0; i < s.length(); i++) {            char c = s.charAt(i);            switch (c) {                case ‘>‘:                    sb.append(">");// 转义大于号                    break;                case ‘<‘:                    sb.append("<");// 转义小于号                    break;                case ‘\‘‘:                    sb.append("'");// 转义单引号                    break;                case ‘\"‘:                    sb.append(""");// 转义双引号                    break;                case ‘&‘:                    sb.append("&");// 转义&                    break;                case ‘#‘:                    sb.append("#");// 转义#                    break;                default:                    sb.append(c);                    break;            }        }        return sb.toString();    }

/**     * xss校验     * @param value     * @return     */    public static String stripXSSAndSql(String value) {        if (StringUtils.isNotEmpty(value)) {            // Avoid null characters            value = value.replaceAll(" ", REPLACE_STRING);            // Avoid anything between script tags            Pattern scriptPattern = Pattern.compile("<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);            value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);            // Avoid anything in a src="http://www.yihaomen.com/article/java/..." type of e-xpression            scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\‘](.*?)[\\\"|\\\‘]", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);            value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);            // Remove any lonesome </script> tag            scriptPattern = Pattern.compile("</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);            value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);            // Remove any lonesome <script ...> tag            scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);            value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);            // Avoid eval(...) expressions            scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);            value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);            // Avoid e-xpression(...) expressions            scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);            value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);            // Avoid javascript:... expressions            scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);            value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);            // Avoid vbscript:... expressions            scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);            value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);            // Avoid onload= expressions            scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);            value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);            // Avoid /r /n:... expressions            scriptPattern = Pattern.compile("\"\\\\s*|\\t|\\r|\\n\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);            value = scriptPattern.matcher(value).replaceAll("");        }        return value;    }

}

过滤的代码写完了,下面就是在一个filter中应用该代码。

XssFilter.java

package com.loger.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @author wbs
 */
@WebFilter(filterName = "xssFilter", urlPatterns = "/*", asyncSupported = true)
@Component public class XssFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; XssAndSqlHttpServletRequestWrapper xssRequestWrapper = new XssAndSqlHttpServletRequestWrapper(req); chain.doFilter(xssRequestWrapper, response); } @Override public void destroy() { } /** * 过滤json类型的 * @param builder * @return */ @Bean @Primary public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) { //解析器 ObjectMapper objectMapper = builder.createXmlMapper(false).build(); //注册xss解析器 SimpleModule xssModule = new SimpleModule("XssStringJsonSerializer"); xssModule.addSerializer(new XssStringJsonSerializer()); objectMapper.registerModule(xssModule); //返回 return objectMapper; } } 

就这样,过滤querystring类型的代码已经完成(xssObjectMapper这个是后面过滤json类型才用到的)。下面来实现过滤json类型的代码:

XssStringJsonSerializer.java

package com.loger.filter;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.apache.commons.text.StringEscapeUtils;

import java.io.IOException;

public class XssStringJsonSerializer extends JsonSerializer<String> {

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

    @Override
    public void serialize(String value, JsonGenerator jsonGenerator,
                          SerializerProvider serializerProvider) throws IOException {
        if (value != null) {
            String encodedValue = StringEscapeUtils.escapeHtml4(value);
            jsonGenerator.writeString(encodedValue);
        }
    }

}

这里通过修改SpringMVC的json序列化来达到过滤xss的目的的。其实也可以通过第一种方法,重写getInputStream方法来实现,但由于得到的是ServletInputStream,不太好处理。(通过json类型传参会走getInputStream方法,通过重写该方法打印输出可以证明)

下面可以通过几个例子验证下是否成功:

简单写一个controller

TestController.java

package com.loger.controller;

import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author wbs
 * Description :
 */
@RestController
@RequestMapping(value = "/test")
public class TestController {

    @PostMapping(value = "/xss")
    public Object test(String name) {
        System.out.println(name);
        return name;
    }

    @PostMapping(value = "/json")
    public Object testJSON(@RequestBody Param param) {
        return param;
    }

    @GetMapping(value = "/query")
    public Object testQuery(String q){
        return q;
    }

    @PostMapping(value = "/upload")
    public Object upload(MultipartFile file){
        System.out.println(file.getOriginalFilename());
        return "OK";
    }

}

下面通过postman测试下效果:

 

图片.png

图片.png

 

原文地址:https://www.cnblogs.com/xiaowangbangzhu/p/10275580.html

时间: 2024-10-20 08:34:37

SpringBoot过滤XSS脚本攻击的相关文章

第二百六十五节,xss脚本攻击介绍

xss脚本攻击介绍 Cross-Site Scripting(XSS)是一类出现在 web 应用程序上的安全弱点,攻击者可以通过 XSS 插入一 些代码,使得访问页面的其他用户都可以看到,XSS 通常是可以被看作漏洞的.它允许攻击者绕过安全机 制,通过尝试各种不同的方法插入恶意代码,攻击者可以得到敏感页面的权限,会话,cookies,或者其 他的东西,XSS 分为三类 XSS 分类: 非持久性,持久性和基于 Dom(此类可以是持久的,也可以是不持久的) 非持久性: 非持久性 XSS 也被称为反射

XSS脚本攻击漫谈

XSS跨站脚本攻击一直都被认为是客户端  Web安全中最主流的攻击方式.因为  Web环境的复杂性以及 XSS跨站脚本攻击的多变性,使得该类型攻击很难彻底解决.那么,XSS跨站脚本攻击具体攻击行为是什么,又该如何进行有效的防范呢?本文对此进行了有针对性的具体实例分析.跨站脚本攻击(Cross Site Scripting)是指攻击者利用网站程序对用户输入过滤不足,输入可以显示在页面上对其他用户造成影响的 HTML代码,从而盗取用户资料.利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方

JAVA覆写Request过滤XSS跨站脚本攻击

注:本文非本人原著. demo的地址:链接:http://pan.baidu.com/s/1miEmHMo 密码:k5ca 如何过滤Xss跨站脚本攻击,我想,Xss跨站脚本攻击令人为之头疼.为什么呢. 尤其是有富文本编辑器的产品.xss可能出现在http的head,不说别的,新浪多次出现. xss可以出现在post数据的正文.图片的url. 于是各种Xss横行,如今Xss跨站脚本漏洞的流行程度甚至超过了当年的sql. 那么对于JAVA语言,如何防御呢. 笔者分享一个思路:所有的web项目,所有的

xss脚本攻击

xss脚本攻击不仅仅只是alert(1)就算完了,xss脚本攻击真正的用处是盗取普通用户的cookie,或者盗取管理员的cookie. xss分类(类型): 1. 反射型xss 2. 存储型xss 3. DOM型xss xss分类(代码): 1.js代码中xss 2.事件中的xss 3.html中的xss 4.外部引入xss 说到外部引入,讲一下同源策略与跨域请求 同源策略: 由Netscape提出的一个著名的安全策略,现在所有支持JavaScript 的浏览器都会使用这个策略,所谓同源是指:协

基于jfinal的XssHandler,统一处理xss脚本攻击

前天公司的网站在<360安全检测>上发现了大量xss漏洞.好吧,我立马懂了,除了我做得有几个模块过滤了之外,别的几乎100%存在! 对于这个东西怎么解决呢?狠是纠结了一番,一个个去改controller吗?好吧这不是我的风格,我没这么勤快!使用拦截器么?(公司使用的是Spring MVC)貌似也解决不了问题?最后使用Filter将问题统一处理OK,其原理是重写掉Request中的getParameter.getParameterValues和getParameterMap方法,使用jsoup清

Fortify漏洞之Cross-Site Scripting(XSS 跨站脚本攻击)

书接上文,继续对Fortify漏洞进行总结,本篇主要针对XSS跨站脚步攻击漏洞进行总结如下: 1.Cross-Site Scripting(XSS 跨站脚本攻击) 1.1.产生原因: 1. 数据通过一个不可信赖的数据源进入 Web 应用程序.对于 Reflected XSS(反射型),不可信赖的源通常为 Web 请求,只影响攻击到当前操作用户:而对于 Persisted(也称为 Stored 持久型)XSS,该源通常为数据库或其他后端数据存储,可能影响多操作用户. 2. 未检验包含在动态内容中的

跨站点脚本攻击(XSS)

XSS分类: (1)反射型XSS:只是简单地把用户输入的数据反射给浏览器.往往需要诱使用户"点击"一个恶意链接.也叫"非持久型XSS" (2)存储型XSS:把用户输入的数据"存储"在服务器端.也叫"持久型XSS" (3)DOM Based XSS:从效果上来说也是反射型XSS,通过修改页面的DOM结点形成的XSS. 1.cookie劫持:httponly或者将cookie和客户端IP绑定可防止 2.XSSPayload: (1

ASP.NET脚本过滤-防止跨站脚本攻击(收集别人的)

ASP.Net 1.1后引入了对提交表单自动检查是否存在XSS(跨站脚本攻击)的能力.当用户试图用<xxxx>之类的输入影响页面返回结果的时候,ASP.Net的引擎会引发一个 HttpRequestValidationExceptioin.默认情况下会返回如下文字的页面: Server Error in '/YourApplicationPath' Application A potentially dangerous Request.Form value was detected from

前端过滤XSS攻击

日常开发过程中,对于存在用户交互的一些门户网站等,过滤xss攻击是必不可少的. 此处主要记录下我在工作过程中的简单处理方法. 前端过滤XSS攻击, 我这里用的是开源工程 js-xss,官网地址:http://jsxss.com/zh/index.html 查看官网可发现,与其他的js库一样,使用js-xss,只需(下载)引入xss.js文件到页面即可. 注意 : xss.js中主要使用到的方法为 filterXSS() 由于我在开发过程中,提交数据多是以表单序列化直接提交的,所以我重写了一下表单