由于跨站脚本会导致会话被劫持、敏感信息泄漏、账户被盗,严重时甚至造成数据修改、删除,从而导致业务中断,因此需检测跨站脚本是否存在
1.web.xml配置
<!-- Character Encoding filter -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>com.harmony.system.security.filter.uCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<!-- 反SQL注入标记 : 用于移动端接口操作数据库时使用,值可自由调整,需与移动端传入参数值一致-->
<param-name>apphttp</param-name>
<param-value>20190430hm</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<!-- -->
<filter>
<filter-name>SessionValidateFilter</filter-name>
<filter-class>com.harmony.system.security.filter.SessionValidateFilter</filter-class>
</filter>
2.uCharacterEncodingFilter.java
public class uCharacterEncodingFilter implements Filter {
protected String encoding = null;
protected FilterConfig filterConfig = null;
protected boolean ignore = true;
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
// Conditionally select and set the character encoding to be used
if (ignore || (request.getCharacterEncoding() == null))
{
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
// Pass control on to the next filter
//00 //对请求进行拦截,防xss处理 ,apphttp 为移动端传入SQL的特定标志
String apphttp = filterConfig.getInitParameter("apphttp");
request.setAttribute("apphttp", apphttp);
chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
//chain.doFilter( request, response);
}
public void init(FilterConfig filterConfig) throws ServletException
{
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter("encoding");
String value = filterConfig.getInitParameter("ignore");
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase("true"))
this.ignore = true;
else if (value.equalsIgnoreCase("yes"))
this.ignore = true;
else
this.ignore = false;
}
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
}
3.XssHttpServletRequestWrapper.java
/**
* 跨站脚本攻击(Cross Site Scripting),缩写为XSS
* xss请求适配器
*/
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
private String apphttp = "";// 移动端SQL 传入标志
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.apphttp = request.getAttribute("apphttp").toString();
}
/**
* 对数组参数进行特殊字符过滤
*/
@Override
public String[] getParameterValues(String name) {
//00 sql 反注入排除法, 排除特定的SQL 传递者
if(!uFunc.IsNullString(super.getParameter("apphttp"))){
String aa = uFunc.getString(super.getParameter("apphttp")) ;
if(aa.equalsIgnoreCase(apphttp)){
return super.getParameterValues(name);
}
}
//00
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] = cleanXSS(values[i]);
}
return encodedValues;
}
/**
* 对参数中特殊字符进行过滤
*/
@Override
public String getParameter(String name) {
//00 sql 反注入排除法, 排除特定的SQL 传递者
if(!uFunc.IsNullString(super.getParameter("apphttp"))){
String aa = uFunc.getString(super.getParameter("apphttp")) ;
if(aa.equalsIgnoreCase(apphttp)){
return super.getParameter(name);
}
}
String value = super.getParameter(name);
if (value == null) {
return null;
}
return cleanXSS(value);
}
/**
* 获取attribute,特殊字符过滤
*/
@Override
public Object getAttribute(String name) {
//00 sql 反注入排除法, 排除特定的SQL 传递者
if(!uFunc.IsNullString(super.getParameter("apphttp"))){
String aa = uFunc.getString(super.getParameter("apphttp")) ;
if(aa.equalsIgnoreCase(apphttp)){
return super.getAttribute(name);
}
}
Object value = super.getAttribute(name);
if (value != null && value instanceof String) {
cleanXSS((String) value);
}
return value;
}
/**
* 对请求头部进行特殊字符过滤
*/
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
if (value == null) {
return null;
}
return value;
//return cleanXSS(value);
}
/**
* 转义字符,使用该方法存在一定的弊端
*
* @param value
* @return
*/
private String cleanXSS2(String value) {
// 移除特殊标签
value = value.replaceAll("<", "<").replaceAll(">", ">");
value = value.replaceAll("\\(", "(").replaceAll("\\)", ")");
value = value.replaceAll("'", "'");
value = value.replaceAll("eval\\((.*)\\)", "");
value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
value = value.replaceAll("script", "");
return value;
}
private String cleanXSS(String value) {
if (value != null) {
//推荐使用ESAPI库来避免脚本攻击,value = ESAPI.encoder().canonicalize(value);
// 避免空字符串
value = value.replaceAll(" ", "");
// 避免script 标签
Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 避免src形式的表达式
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
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("");
// 避免 eval(...) 形式表达式
scriptPattern = Pattern.compile("eval\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 expression(...) 表达式
scriptPattern = Pattern.compile("expression\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 javascript: 表达式
scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 vbscript:表达式
scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
// 避免 onload= 表达式
scriptPattern = Pattern.compile("onload(.*?)=",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
// 第二种是采用正则表达式将包含有 单引号('),分号(;) 和 注释符号(--)的语句给替换掉来防止SQL注入
//00 Java防止SQL注入
value =value.replaceAll(".*([';]+|(--)+).*", " ");
/* public static String TransactSQLInjection(String str)
{
return str.replaceAll(".*([';]+|(--)+).*", " ");
// 我认为 应该是return str.replaceAll("([';])+|(--)+","");
}*/
}
return value;
}
}
提示:如果要往后台中传递参数包含空格、特殊字符等,可在传递参数中加apphttp=20190430hm防止被过滤器过滤掉