天天看点

XSS跨站脚本攻击(三)-- 结合Spring MVC框架

1.web.xml中

<filter>  
<filter-name>xssFilter</filter-name>  
<filter-class>com.xxx.web.filter.XSSFilter</filter-class>  
</filter>  
<filter-mapping>  
<filter-name>xssFilter</filter-name>  
<url-pattern>/*</url-pattern>  
</filter-mapping>  
           

2.XSSFilter.java

package com.xxx.web.filter;  
  
import java.io.IOException;  
  
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
import javax.servlet.http.HttpServletRequest;  
           
import org.apache.commons.lang.StringEscapeUtils;
  
 public class XssFilter implements Filter {  
  
   FilterConfig  filterConfig;
   public void init(FilterConfig config) throws ServletException {  
       this.filterConfig =  filterConfig;
   }  
  
   public void doFilter(ServletRequest request, ServletResponse response,  
      FilterChain chain) throws IOException, ServletException {  
      XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);  
      chain.doFilter(xssRequest, response);  
   }  
  
   public void destroy() {  
      this.filterConfig =  null;
   }  
}
           

3. XssHttpServletRequestWrapper.java

某些情况下,我们不能对用户数据进行严格的过滤,那我们也需要对标签进行转换。

less-than character (<) &lt;
greater-than character (>) &gt;
ampersand character (&) &amp;
double-quote character (") &quot;
space character( )
Any ASCII code character whose code is greater-than or equal to 0x80 &#<number>, where <number> is the ASCII character value.

      比如用户输入:<script>window.location.href=”http://www.baidu.com”;</script>,保存后最终存储的会是:&lt;script&gt;window.location.href=&quot;http://www.baidu.com&quot;&lt;/script&gt;在展现时浏览器会对这些字符转换成文本内容显示,而不是一段可执行的代码。

package com.xxx.web.filter;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletRequestWrapper;  
  
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {  
public XssHttpServletRequestWrapper(HttpServletRequest request) {  
super(request);
}  
@Override  
public String[] getParameterValues(String parameter) {  
String[] values = super.getParameterValues(parameter);  
if (values == null) {  
   return null;  
}  
int count = values.length;
String[] encodedValues = new String[count];
for(int i=0;i<count;i++){
   //encodedValues[i] = StringEscapeUtils.escapeHtml(values[i]);
    encodedValues[i] = this.escapeHtml(values[i]);
}
return encodedValues;  
}

@Override  
public String getParameter(String parameter) {  
String value = super.getParameter(parameter);  
if (value == null) {  
    return null;  
}  
   //return StringEscapeUtils.escapeHtml(value);
    return this.escapeHtml(value);
}  
  
/** 
* 重写StringEscapeUtils.escapeHtml()方法,避免过滤中文 
* 
* @param s 
* @return 
*/  
private String escapeHtml(String s) {  
 if (s == null || s.isEmpty()) {  
   return "";  
 }  
StringBuilder sb = new StringBuilder("");  
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 10:  
case 13:  
break; 
default:  
sb.append(c);  
break;  
}  
}  
return sb.toString();  
}   
} 
           

4.针对上面重写StringEscapeUtils.escapeHtml()方法,主要是,从前端传入后台的数据,如果是中文的话,使用StringEscapeUtils.escapeHtml(value)就会把中文也转码了,这样不是我们希望看到的。,因此需要重写方法。

5.如果我们前端传的参数是一个json串,那么到了后端需要对双引号特殊处理,比如:

前端:

var arrChoosed = [{"id":parseInt('10'),"name":"詹三"},{.....}];

ajax传入后端参数为data:{'params':JSON.stringify(arrChoosed),.....}

后端:

String parameter = request.getParameter("params").replaceAll("&quot;","\"");

ObjectMapper mapper = new ObjectMapper();

List<Map<String,Object>> paramList = mapper.readValue(parameter,List.class);

6.针对Spring MVC中的@RequestParam获取的参数,走的是3中的getParameterValues()方法。

继续阅读