跨站脚本 XSS<一:防御方法>
1. 过滤特殊字符
避免XSS的方法之一主要是将用户所提供的内容进行过滤,许多语言都有提供对HTML的过滤:
- PHP的
htmlentities()或是htmlspecialchars()
。 - Python的
cgi.escape()
。 - ASP的
Server.HTMLEncode()
。 - ASP.NET的
Server.HtmlEncode()
或功能更强的Microsoft Anti-Cross Site Scripting Library - Java的xssprotect (Open Source Library)。
- Node.js的node-validator。
2. 应用<java语言>
在web应用中主要是通过在过滤器中将可能造成攻击的字符进行转义,转义之后存到数据库中,从而避免攻击。
XSSFilter.java过滤器配置
package util.web; import *; /** * xss过滤器和CSRF过滤 * 防 XSS 之全角替换半角 * 防CSRF之HTTP 头设置 Referer过滤 * */ public class XSSFilter implements Filter { @Override public void init(FilterConfig filterconfig) throws ServletException { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest servletrequest,ServletResponse servletresponse, FilterChain filterchain)throws IOException, ServletException { // 防 XSS XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest)servletrequest);//***包装转换请求中的可能攻击的字段 filterchain.doFilter(xssRequest, httpResp); } @Override public void destroy() { // TODO Auto-generated method stub } }
XssHttpServletRequestWrapper .java 主要重写getParameter()和getParameterValues()方法,对获取的值进行转义。
package util.web; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; /** * 针对普通字符串进行过滤转义 * 本质是把符号额度半角变成全角 * 这样JS就执行不了了*/ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { HttpServletRequest orgRequest = null; public XssHttpServletRequestWrapper(HttpServletRequest request) { super(request); orgRequest = request; } /** * 覆盖getParameter方法,将参数名和参数值都做xss过滤。<br/> * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/> * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 */ @Override public String getParameter(String name) { String value = super.getParameter(xssEncode(name)); if(value != null) { value = xssEncode(value); } return value; } @Override public String[] getParameterValues(String name) { String[]parameters=super.getParameterValues(name); if (parameters==null||parameters.length == 0) { return null; } for (int i = 0; i < parameters.length; i++) { parameters[i] = xssEncode(parameters[i]); } return parameters; } /** * 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/> * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/> * getHeaderNames 也可能需要覆盖 */ @Override public String getHeader(String name) { String value = super.getHeader(xssEncode(name)); if(value != null) { value = xssEncode(value); } return value; } /** * 将容易引起xss漏洞的半角字符直接替换成全角字符 * * @param s * @return */ private static String xssEncode(String s) { if(s == null|| s.isEmpty()) { return s; } StringBuilder sb = new StringBuilder(s.length() + 16); 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(""");// 转义双引号 ;***先注释掉,会影响json的转化 break; */ case'&': sb.append("&");// 转义& break; default: sb.append(c); break; } } return sb.toString(); } /** * 获取最原始的request * * @return */ public HttpServletRequest getOrgRequest() { return orgRequest; } /** * 获取最原始的request的静态方法 * * @return */ public static HttpServletRequest getOrgRequest(HttpServletRequest req) { if(req instanceof XssHttpServletRequestWrapper) { return((XssHttpServletRequestWrapper) req).getOrgRequest(); } return req; } }
3.结论
以上的方法中只是提供的一个简单和原理性的实现,在getParameter()和getParameterValues()方法中调用 xssEncode() 方法转义。
附:
通过Apache的一个xss转义项目也可以实现:https://code.google.com/archive/p/xssprotect/wikis/HowTouse.wiki
参考资料:
1.http://itindex.net/detail/46431-xssproject-java-web
2.http://liuzidong.iteye.com/blog/1744023