XSS过滤器Filter实现

需求:xxs攻击过滤

测试发现代码转换成图片格式后,可以通过上传文件接口存在服务器上,再次打开时候会执行代码

项目背景:前端采用form+ajax提交数据,后端采用SpringMVC框架,@RequestMapping注解的方法接收前端参数。其中还有用到multipart/form-data传输文件。

思路:
一、实现XSSFilter类(包括工具类和multipartResolver的使用)
二、实现XssHttpServletRequestWraper类
三、注册过滤器(配置类XssConfig和web.xml两种方式)

1.创建过滤器类

1.1XssFilter

在XssFilter需要使用ApplicationContext在初始化filter时候注入multipartResolver,

所以filter需ApplicationContextUtils工具类。filter初始化建立在ApplicationContextUtils加载的基础上,所以需要注释

@DependsOn({"applicationContextUtils"})

详情见SpringBoot使用ApplicationContext.getBean启动报空指针处理记录

package xxxx.web.filter.xss;

import xxxx.web.utils.ApplicationContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.MultipartResolver;

import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.*;
import java.io.IOException;

@Component
@DependsOn({"applicationContextUtils"})
public class XssFilter implements Filter{
    //	为了解决multipart/form-data过滤器过滤之后controller接收不到数据的问题
    @Autowired
    private MultipartResolver multipartResolver=null;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //注入bean
        multipartResolver=(MultipartResolver) ApplicationContextUtils.getApplicationContext().getBean("multipartResolver",MultipartResolver.class);
    }

    @Override
    public void doFilter(ServletRequest request , ServletResponse response , FilterChain chain)
            throws IOException, ServletException{
        String contentType=request.getContentType();
        if(contentType!=null && contentType.contains("multipart/form-data")){
            //form-data过滤
            MultipartHttpServletRequest multipartRequest=multipartResolver.resolveMultipart((HttpServletRequest) request);
            XssHttpServletRequestWraper xssRequest=new XssHttpServletRequestWraper(multipartRequest);
            chain.doFilter(xssRequest, response);
        }else{
            //普通过滤
            XssHttpServletRequestWraper xssRequest=new XssHttpServletRequestWraper((HttpServletRequest)request);
            chain.doFilter(xssRequest, response);
        }
    }

    @Override
    public void destroy(){

    }
}

1.2 工具类ApplicationContextUtils

package xxx.web.utils;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;

import java.util.Locale;


//对Spring容器进行各种上下文操作的工具类
@Configuration
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        ApplicationContextUtils.context = context;
    }

    public static ApplicationContext getApplicationContext(){
        return context;
    }
    //根据Bean名称获取Bean对象
    public static Object getBean(String beanName){
        return context.getBean(beanName);
    }

    public static Object getMassage(String key){
        return context.getMessage(key, null, Locale.getDefault());
    }
}

1.3multipartResolver文件上传配置

我感觉上传文件可以做到零配置,但是此处项目用到的是不限制文件大小,仅供参考
 

spring.servlet.multipart.enabled=true
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1

 很多文章中此处用了xml方式

	<!-- =========================注册文件上传 -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
		<!-- 文件上传大小限制 -->
		<property name="maxUploadSize">
			<value>104857600</value>
		</property>
		<property name="defaultEncoding">
			<value>UTF-8</value>
		</property>
	</bean>
	

文件上传使用multipartResolver具体解析如下:

文件上传解析器MultipartResolver

springBoot中整合文件上传的配置

2.XssHttpServletRequestWraper

package xxx.web.filter.xss;

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


public class XssHttpServletRequestWraper extends HttpServletRequestWrapper {

    public XssHttpServletRequestWraper(HttpServletRequest servletRequest){
        super(servletRequest);
    }

    @Override
    public String getHeader(String name){
        return super.getHeader(name);
    }

    @Override
    public String getParameter(String name){
        String value = super.getParameter(name);
        return xssEncode(value);
    }

    //对以FormData形式提交,Content-Type:application/x-www-from-urlencoded参数过滤
    @Override
    public String[] getParameterValues(String name){
        String[] values=super.getParameterValues(name);
        if(values==null){
            return null;
        }
        int count=values.length;
        String[] encodeValues=new String[count];
        for(int i=0;i<count;i++){
            encodeValues[i]=xssEncode(values[i]);
        }
        return encodeValues;
    }

    /*过滤策略:把特殊字符转为HTML实体编码,
     *这样存在数据库里较安全
     *返回给前端时会被js解析为正常字符,不影响查看*/
    public static String xssEncode(String str){
        if(str == null || str.isEmpty()){
            return str;
        }
        str = str.replaceAll(";", "&#59;");
        str = str.replaceAll("<", "&#60;").replaceAll(">", "&#62;");
        str = str.replaceAll("\\(", "&#40;").replaceAll("\\)", "&#41;");
        str = str.replaceAll("'", "&#39;").replaceAll("\"", "&#34;");
        str = str.replaceAll("\\$", "&#36;");
        str = str.replaceAll("%", "&#37;");
        str = str.replaceAll("\\/", "&#47;").replaceAll("\\\\", "&#92;");
        str = str.replaceAll(":", "&#58;");
        str = str.replaceAll("\\?", "&#63;").replaceAll("@", "&#64;");
        str = str.replaceAll("\\^", "&#94;");
        return str;
    }
}

3.注册过滤器

3.1配置类XssConfig

        在这个配置类中,我们通过FilterRegistrationBean来注册XssFilter。setOrder方法用于设置过滤器的执行顺序,addUrlPatterns方法用于指定过滤器应该应用于哪些URL模式,setDispatcherTypes方法用于指定过滤器应该拦截的请求类型(如REQUEST、FORWARD、INCLUDE、ERROR等)。

package xxx.web.filter.xss;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import javax.servlet.DispatcherType;
import org.springframework.context.annotation.Configuration;

@Configuration
public class XssConfig {
    @Autowired
    private XssFilter xssFilter;
    @Bean
    public FilterRegistrationBean<XssFilter> xssFilterRegistration() {
        FilterRegistrationBean<XssFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(xssFilter);
        registration.setOrder(Integer.MAX_VALUE); // 设置过滤器顺序
        registration.addUrlPatterns("/*"); // 设置过滤器的URL模式
        registration.setDispatcherTypes(DispatcherType.REQUEST); // 指定过滤器应该拦截的类型
        return registration;
    }
}

3.2web.xml配置过滤器

<filter>
	<filter-name>XssFilter</filter-name>
	<filter-class>XssFilter在项目存放的位置</filter-class>
</filter>
<filter-mapping>
	<filter-name>XssFilter</filter-name>
	<url-partten>/*</url-partten>
	<dispatcher>REQUEST</dispatcher>
</filter-mapping>

结果:

<script>alert("1");</script>
后台会解析为&#60;script&#62;alert&#40;&#34;1&#34;&#41;&#59;&#60;&#47;script&#62;
并存入数据库,而在前端显示时又会显示为原来的字符,且不会执行js语句。

返回给前端时,如果是html(str)显示,则能显示原来字符。如果是val(str)返回给文本框的话,则并不会把HTML实体字符解析为正常字符。所以需要我们写个解析函数。在此略

一、什么是XSS攻击 XSS是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。比如这些代码包括HTML代码和客户端脚本。攻击者利用XSS漏洞旁路掉访问控制——例如同源策略(same origin policy)。这种类型的漏洞由于被黑客用来编写危害性更大的网络钓鱼(Phishing)攻击而变得广为人知。对于跨站脚本攻击,黑客界共识是:跨站脚本攻击是新型的“缓冲区溢出攻击“,而JavaScript是新型的“ShellCode”。 二、XSS漏洞的危害 (1)网络钓鱼,包括盗取各类用户账号; (2)窃取用户cookies资料,从而获取用户隐私信息,或利用用户身份进一步对网站执行操作; (3)劫持用户(浏览器)会话,从而执行任意操作,例如进行非法转账、强制发表日志、发送电子邮件等; (4)强制弹出广告页面、刷流量等; (5)网页挂马; (6)进行恶意操作,例如任意篡改页面信息、删除文章等; (7)进行大量的客户端攻击,如DDoS攻击; (8)获取客户端信息,例如用户的浏览历史、真实IP、开放端口等; (9)控制受害者机器向其他网站发起攻击; (10)结合其他漏洞,如CSRF漏洞,实施进一步作恶; (11)提升用户权限,包括进一步渗透网站; (12)传播跨站脚本蠕虫等; 三、过滤器配置 web.xml配置 XssFilter com.xxx.Filter.XssFilter XssFilter /*
以下是一个简单的Spring Boot XSS过滤器的代码实现: 1. 创建一个名为XSSFilterJava类,并实现javax.servlet.Filter接口。 ```java @Component public class XSSFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response); } // ... } ``` 2. 创建一个名为XSSRequestWrapper的Java类,该类继承HttpServletRequestWrapper类,并覆盖getParameter()方法以过滤请求参数中的HTML和JavaScript代码。 ```java public class XSSRequestWrapper extends HttpServletRequestWrapper { public XSSRequestWrapper(HttpServletRequest request) { super(request); } @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] = cleanXSS(values[i]); } return encodedValues; } @Override public String getParameter(String parameter) { String value = super.getParameter(parameter); return cleanXSS(value); } private String cleanXSS(String value) { // 过滤掉HTML和JavaScript代码 return Jsoup.clean(value, Whitelist.basic()); } } ``` 在上面的示例中,使用了Jsoup库的clean方法来过滤HTML和JavaScript代码,并使用Whitelist.basic()方法配置了基本的白名单。 3. 将过滤器注册到Spring Boot应用程序中,并将其应用于需要防止XSS攻击的URL路径。 ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private XSSFilter xssFilter; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(xssFilter).addPathPatterns("/secure/*"); } } ``` 在上面的示例中,XSS过滤器被应用于/secure/*路径下的所有请求。您可以根据需要更改路径。 这是一个简单的XSS过滤器实现,您可以根据自己的需求进行扩展和定制化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值