Overview of XSS
Cross Site Scripting (Cross Site Scripting), abbreviated as XSS. Malicious attackers insert malicious Script code into a Web page. When a user browses the page, the Script code embedded in the Web page will be executed, thereby achieving the purpose of maliciously attacking the user.
Implement Filter, implement XSS filter
package com.bj58.qf.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* Created with IntelliJ IDEA.
*
* @author: zhubo
* @description: 防止XSS注入攻击Filter过滤器
* @time: 2018年05月02日
* @modifytime:
*/
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 {
//对请求进行拦截,防xss处理
chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request),response);
}
@Override
public void destroy() {
}
}
Inherit HttpServletRequestWrapper to filter request parameters
package com.bj58.qf.filter;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.regex.Pattern;
/**
* Created with IntelliJ IDEA.
*
* @author: zhubo
* @description:
* @time: 2018年05月02日
* @modifytime:
*/
public class XSSRequestWrapper extends HttpServletRequestWrapper {
boolean isUpData = false;//判断是否是上传 上传忽略
public XSSRequestWrapper(HttpServletRequest request) {
super(request);
String contentType = request.getContentType();
if (null != contentType){
isUpData =contentType.startsWith ("multipart");
}
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
return stripXSS(value);
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values == null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = stripXSS(values[i]);
}
return encodedValues;
}
/**
* 获取request的属性时,做xss过滤
*/
@Override
public Object getAttribute(String name) {
Object value = super.getAttribute(name);
if (null != value && value instanceof String) {
value = stripXSS((String) value);
}
return value;
}
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
return value;
}
private String stripXSS(String value) {
if (value != null) {
value = value.replaceAll(" ", "");
// Avoid anything in a <script>alert(a);</script>" type of expression
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 删除单个的 </script> 标签
scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 删除单个的<script ...> 标签
scriptPattern = Pattern.compile("<script(.*?)>",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid eval(...) expressions
scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid expression(...) expressions
scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid javascript:... expressions
scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid vbscript:... expressions
scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// Avoid onload= expressions
scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
}
return value;
}
@Override
public ServletInputStream getInputStream () throws IOException {
if (isUpData){
return super.getInputStream ();
}else{
final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream()).getBytes(Charset.forName("UTF-8")));
return new ServletInputStream() {
@Override
public int read() throws IOException {
return bais.read();
}
};
}
}
public String inputHandlers(ServletInputStream servletInputStream){
StringBuilder sb = new StringBuilder();
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));
String line = "";
while ((line = reader.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (servletInputStream != null) {
try {
servletInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return stripXSS(sb.toString());
}
}
3. Inject XSS filter, two ways
The first way: configure web.xml
<!-- xss过滤器 -->
<filter>
<filter-name>XssSqlFilter</filter-name>
<filter-class>cn.aric.xss.XssFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XssSqlFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
The second way: annotation
/**
* 注入Xss过滤器(注解方式)
*/
public class WebInitializer implements WebApplicationInitializer{
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
//添加监听器
servletContext.addListener(RequestContextListener.class);
//添加过滤器
Dynamic xssFilterRegistration = servletContext.addFilter("XssFilter", XssFilter.class);
//添加映射规则
xssFilterRegistration.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.REQUEST,DispatcherType.FORWARD,DispatcherType.INCLUDE),
false,
"/*");
}
}