什么是XSS?
XSS攻击全称跨站脚本攻击,是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。
也就是说,在日常所常用的表单中,我们内嵌一段js代码提交,用户通过访问再从数据库中取出这段代码,就会跟随页面进行执行,甚至可以发送cookie,跳转网站等等。
我们可以使用以下代码填入表单中验证系统是否存在XSS问题。
<script>alert("xss")</script>
使用Antisamy进行XSS过滤
AntiSamy是OWASP的一个开源项目,通过对用户输入的 HTML / CSS / JavaScript 等内容进行检验和清理,确保输入符合应用规范。AntiSamy被广泛应用于Web服务对存储型和反射型XSS的防御中。
如何使用?
引入依赖和配置文件
首先我们引入maven依赖。
<dependency>
<groupId>org.owasp.antisamy</groupId>
<artifactId>antisamy</artifactId>
<version>RELEASE</version>
</dependency>
引入之后,我们可以通过查看jar包可以发现,AntiSamy自带了多个配置文件:
其中,这些常用的配置文件介绍如下:
- antisamy-anythinggoes.xml
允许所有有效的HTML和CSS元素输入(但能拒绝JavaScript或跟CSS相关的网络钓鱼攻击),因为它包含了对于每个元素的基本规则,所以你在裁剪其它策略文件的时候可以把它作为一个知识库,一般不建议使用。 - antisamy-ebay.xml
eBay 是当下最流行的在线拍卖网站之一。它是一个面向公众的站点,因此它允许任何人发布一系列富HTML的内容,允许输入的内容列表包含了比 Slashdot 更多的富文本内容,所以它的受攻击面也要大得多。
该策略相对安全,适用于电子商务网站。 - antisamy-myspace.xml
MySpace 是最流行的一个社交网站之一。用户允许提交除了JavaScript之外的几乎所有他们想用的HTML和CSS。
MySpace现在用一个黑名单来验证用户输入的HTML,相对较危险,不建议使用。 - antisamy-slashdot.xml
Slashdot 是一个提供技术新闻的网站,其安全策略非常严格。用户只能提交下列的HTML标签:< b>、< u>、< i>、< a>、< blockquote>,并且还不支持CSS。
该策略文件来实现了类似的功能,允许所有文本格式的标签来直接修饰字体、颜色或者强调作用,适用于新闻网站的评论过滤。 - antisamy-tinymce.xml
只允许文本格式通过,相对较安全 - antisamy.xml
默认规则,允许大部分HTML通过
这里,我们使用slashdot配置文件,将此文件复制到resource目录中即可开始使用。
创建XSSFilter过滤器
通过doFilter方法来对传入的request过滤
package cn.vwmwv.hgnuman.congfig;
import cn.vwmwv.hgnuman.filter.XssFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AntiSamyConfiguration {
// 过滤器配置文件
@Bean
public FilterRegistrationBean filterRegistrationBean(){ // XSS过滤器
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new XssFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
}
创建XssRequestWrapper
package cn.vwmwv.hgnuman.filter;
import org.owasp.validator.html.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class XssRequestWrapper extends HttpServletRequestWrapper {
/**
* Constructs a request object wrapping the given request.
*
* @param request the {@link HttpServletRequest} to be wrapped.
* @throws IllegalArgumentException if the request is null
*/
public XssRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String[] getParameterValues( String name){
String[] values = super.getParameterValues( name);
if ( values == null){
return null;
}
int len = values.length;
String[] newArray = new String[len];
for (int j = 0; j < len; j++){
// 过滤
newArray[j] = xssClean( values[j]);
}
return newArray;
}
/**
* 策略文件
* 注意,需要将要使用的策略文件放到项目资源文件路径下
* */
private static String antiSamyPath = XssRequestWrapper.class.getClassLoader()
.getResource( "antisamy-slashdot.xml").getFile(); // 这里选择配置文件
/**
* AntiSamy过滤数据
* @param taintedHTML 需要进行过滤的数据
* @return 返回过滤后的数据
* */
private String xssClean( String taintedHTML){
try{
// 指定策略文件
Policy policy = Policy.getInstance(antiSamyPath);
// 使用AntiSamy进行过滤
AntiSamy antiSamy = new AntiSamy();
CleanResults cr = antiSamy.scan( taintedHTML, policy);
taintedHTML = cr.getCleanHTML();
}catch( ScanException e) {
e.printStackTrace();
}catch( PolicyException e) {
e.printStackTrace();
}
return taintedHTML;
}
}
创建AntiSamy路由过滤配置
/*
* Copyright (c) 2021. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
* Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan.
* Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna.
* Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus.
* Vestibulum commodo. Ut rhoncus gravida arcu.
*/
package cn.vwmwv.hgnuman.congfig;
import cn.vwmwv.hgnuman.filter.XssFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AntiSamyConfiguration {
// 过滤器配置文件
@Bean
public FilterRegistrationBean filterRegistrationBean(){ // XSS过滤器
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new XssFilter());
filterRegistrationBean.addUrlPatterns("/*"); // 通过“ /* ”来匹配所以的提交路由,也就是对所有提交生效
filterRegistrationBean.setOrder(1); // 设置优先级
return filterRegistrationBean;
}
}