网络安全——预防XSS
XSS是网络安全界沉睡的巨人,如果系统设计者没有考虑到相关的防范措施,后果很严重。下面记录了通过过滤器实现XSS过滤的主要步骤,以供参考。
过滤规则
针对XSS过滤网络上有很多方式,比如将可能引发XSS的<,>等转换为全角,将script相关直接替换掉,在存储字符串时通过Apache的html转义工具转义,查询时再反转义回来等。这次我选择的是Apache基金下的sling框架,它提供了针对XSS的过滤,做法是将容易引发XSS的关键字全部替换为空字符串,简单暴力!
Maven依赖
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.xss</artifactId>
<version>${sling-xss.version}</version>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.api</artifactId>
<version>${sling-api.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>${felix-annoatation.version}</version>
</dependency>
Xss过滤器
/**
* XSS过滤器
*
* @author ald
* @date 2017/1/4 22:55
*/
public class XssFilter implements Filter {
private static final Logger log = LoggerFactory.getLogger(XssFilter.class);
private XSSFilter slingXssFilter;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
slingXssFilter = new XSSFilterImpl();
InputStream inputStream = XssFilter.class.getClassLoader().getResourceAsStream("SLING-INF/content/config.xml");
try {
((XSSFilterImpl)slingXssFilter).setDefaultPolicy(inputStream);
} catch (Exception e) {
log.error("sling xssFilter set default policy failure",e);
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(new XssHttpServletRequest((HttpServletRequest) request,slingXssFilter), response);
}
@Override
public void destroy() {
slingXssFilter = null;
}
}
/**
* XSS请求包装类
*
* @author ald
* @date 2016/12/28 9:58
*/
public class XssHttpServletRequest extends HttpServletRequestWrapper {
private XSSFilter slingXssFilter;
public XssHttpServletRequest(HttpServletRequest request, XSSFilter slingXssFilter) {
super(request);
this.slingXssFilter = slingXssFilter;
}
@Override
public String getQueryString() {
String queryStr = super.getQueryString();
return queryStr==null?queryStr:slingXssFilter.filter(queryStr);
}
@Override
public String getParameter(String name) {
String parameter = super.getParameter(name);
return parameter==null?parameter:slingXssFilter.filter(parameter);
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (values==null || values.length==0){
return new String[0];
}
for (int i=0; i<values.length; i++){
values[i] = slingXssFilter.filter(values[i]);
}
return values;
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> parameterMap = super.getParameterMap();
for (Map.Entry<String, String[]> entry:parameterMap.entrySet()){
String[] values = entry.getValue();
if (values!=null && values.length>0){
for (int i=0; i<values.length; i++){
values[i] = slingXssFilter.filter(values[i]);
}
}
parameterMap.put(entry.getKey(),values);
}
return parameterMap;
}
@Override
public String getHeader(String name) {
String header = super.getHeader(name);
return header==null?header:slingXssFilter.filter(header);
}
}
原理:通过包装类,重写request的getParameter等方法,然后用sling将参数值过滤