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.apachemons.lang3.StringUtils;
import 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);
}
@Override
public String getParameter(String name) {
String value = Parameter(name);
if (!StringUtils.isEmpty(value)) {
value = StringEscapeUtils.escapeHtml4(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] parameterValues = ParameterValues(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.apachemons</groupId>
<artifactId>commons-text</artifactId>
<version>1.4</version>
</dependency>
 //如果使⽤的是上⾯黄⾊的⾃定义⼯具类,来过滤xss 关键字,就需要导⼊下⾯XssUtils⼯具类,如果不使⽤的话下⾯这个⼯具类,就直接跳过不需要管。但是有些⼈说为啥有第三⽅⼯具类,还要使⽤⾃定义⼯具类呢,应为使⽤第三⽅插件时,进⾏代码扫描时(我们公司项⽬上线需要进⾏代码扫描)会有问题(这个问题不影响代码使⽤),所以我⽤的是⾃定义类。总之这两种⼯具类都可以⽤,不影响功能的实现。
/**
spring framework是什么框架的* @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;
}
}
String();
}
/
**
* xss校验
* @param value
* @return
*/
public static String stripXSSAndSql(String value) {
if (StringUtils.isNotEmpty(value)) {
// Avoid null characters
value = placeAll(" ", REPLACE_STRING);
// Avoid anything between script tags
Pattern scriptPattern = Patternpile("<[\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="www.yihaomen/article/java/..." type of e-xpression
scriptPattern = Patternpile("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 = Patternpile("</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);
// Remove any lonesome <script ...> tag
scriptPattern = Patternpile("<[\r\n| | ]*script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);
// Avoid eval(...) expressions
scriptPattern = Patternpile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);
// Avoid e-xpression(...) expressions
scriptPattern = Patternpile("e-xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);
// Avoid javascript:... expressions
scriptPattern = Patternpile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);
// Avoid vbscript:... expressions
scriptPattern = Patternpile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);
// Avoid onload= expressions
scriptPattern = Patternpile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll(REPLACE_STRING);
// Avoid /r /n:... expressions
scriptPattern = Patternpile("\"\\\\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.dule.SimpleModule;
import t.annotation.Bean;
import t.annotation.Primary;
import org.verter.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) 就这样,过滤querystring类型的代码已经完成(xssObjectMapper这个是后⾯过滤json类型才⽤到的)。下⾯来实现过滤json类型的代码:
XssStringJsonSerializer.java
package com.loger.filter;
import com.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import 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的⽬的的。其实也可以通过第⼀种⽅法,重写getI
nputStream⽅法来实现,但由于得到的是ServletInputStream,不太好处理。(通过json类型传参会⾛getInputStream⽅法,通过重写该⽅法打印输出可以证明)
下⾯可以通过⼏个例⼦验证下是否成功:
简单写⼀个controller
TestController.java
package ller;
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.OriginalFilename());
return "OK";
}
}
下⾯通过postman测试下效果:
图⽚.png
图⽚.png

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。