package com.whyc.filter;
|
|
import org.owasp.esapi.ESAPI;
|
|
import javax.servlet.ReadListener;
|
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.StandardCharsets;
|
import java.util.HashMap;
|
import java.util.Map;
|
import java.util.regex.Pattern;
|
|
import static java.util.regex.Pattern.*;
|
|
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
private Map<String, String[]> params;
|
|
public XssHttpServletRequestWrapper(HttpServletRequest request, Map<String, String[]> newParams) throws IOException {
|
super(request);
|
|
params=new HashMap<String, String[]>();
|
|
for(String key:newParams.keySet()){
|
String[] value=newParams.get(key);
|
int count = value.length;
|
String[] encodedValues = new String[count];
|
for (int i = 0; i < count; i++) {
|
encodedValues[i] =cleanXSS(value[i]);
|
}
|
params.put(key, encodedValues);
|
}
|
|
}
|
|
/**请求url参数处理*/
|
@Override
|
public String[] getParameterValues(String parameter) {
|
|
String[] values = super.getParameterValues(parameter);
|
if (values != null){
|
|
int length = values.length;
|
String[] encodedValues = new String[length];
|
for (int i = 0; i < length; i++)
|
{
|
encodedValues[i] = cleanXSS(values[i]);
|
}
|
return encodedValues;
|
}
|
return null;
|
}
|
@Override
|
public String getParameter(String parameter) {
|
|
String value = super.getParameter(parameter);
|
return cleanXSS(value);
|
}
|
|
|
@Override
|
public Map<String, String[]> getParameterMap() {
|
return params;
|
}
|
|
/**Json请求体参数处理*/
|
@Override
|
public ServletInputStream getInputStream() throws IOException {
|
final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream()).getBytes(StandardCharsets.UTF_8));
|
|
return new ServletInputStream() {
|
|
@Override
|
public int read() throws IOException {
|
return bais.read();
|
}
|
|
@Override
|
public boolean isFinished() {
|
return false;
|
}
|
|
@Override
|
public boolean isReady() {
|
return false;
|
}
|
|
@Override
|
public void setReadListener(ReadListener readListener) { }
|
};
|
}
|
|
public String inputHandlers(ServletInputStream servletInputStream){
|
StringBuilder sb = new StringBuilder();
|
BufferedReader reader = null;
|
try {
|
reader = new BufferedReader(new InputStreamReader(servletInputStream, StandardCharsets.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 cleanXSS(sb.toString ());
|
}
|
|
@Override
|
public String getHeader(String name) {
|
|
String value = super.getHeader(name);
|
return cleanXSS(value);
|
}
|
private String cleanXSS(String value) {
|
if (value != null) {
|
// 推荐使用ESAPI库来避免脚本攻击,同时对所有的url编码数据进行了完全解码操作
|
value = ESAPI.encoder().canonicalize(value);
|
|
// 避免空字符串
|
//value = value.replaceAll(" ", "");
|
|
// 删除 '
|
value = value.replaceAll("'","");
|
|
// 避免script 标签
|
Pattern scriptPattern = compile("<script>(.*?)</script>", CASE_INSENSITIVE);
|
value = scriptPattern.matcher(value).replaceAll("");
|
//避免src形式的表达式
|
scriptPattern = compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", CASE_INSENSITIVE | MULTILINE | DOTALL);
|
value = scriptPattern.matcher(value).replaceAll("");
|
|
scriptPattern = compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", CASE_INSENSITIVE | MULTILINE | DOTALL);
|
value = scriptPattern.matcher(value).replaceAll("");
|
|
// 删除单个的 </script> 标签
|
scriptPattern = compile("</script>", CASE_INSENSITIVE);
|
value = scriptPattern.matcher(value).replaceAll("");
|
|
// 删除单个的<script ...> 标签
|
scriptPattern = compile("<script(.*?)>", CASE_INSENSITIVE | MULTILINE | DOTALL);
|
value = scriptPattern.matcher(value).replaceAll("");
|
|
// 避免 eval(...) 形式表达式
|
scriptPattern = compile("eval\\((.*?)\\)", CASE_INSENSITIVE | MULTILINE | DOTALL);
|
value = scriptPattern.matcher(value).replaceAll("");
|
|
// 避免 expression(...) 表达式
|
scriptPattern = compile("expression\\((.*?)\\)", CASE_INSENSITIVE | MULTILINE | DOTALL);
|
value = scriptPattern.matcher(value).replaceAll("");
|
|
// 避免 javascript: 表达式
|
scriptPattern = compile("javascript:", CASE_INSENSITIVE);
|
value = scriptPattern.matcher(value).replaceAll("");
|
|
// 避免 vbscript: 表达式
|
scriptPattern = compile("vbscript:", CASE_INSENSITIVE);
|
value = scriptPattern.matcher(value).replaceAll("");
|
|
// 避免 onload= 表达式
|
scriptPattern = compile("onload(.*?)=", CASE_INSENSITIVE | MULTILINE | DOTALL);
|
value = scriptPattern.matcher(value).replaceAll("");
|
|
// 避免 onXX= 表达式
|
/*scriptPattern = compile("on.*(.*?)=", CASE_INSENSITIVE | MULTILINE | DOTALL);
|
value = scriptPattern.matcher(value).replaceAll("");*/
|
|
}
|
return value;
|
}
|
|
}
|