基于Servlet实现web项目跨站脚本注入

package com.zemso.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;

public class XSSFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        request.setCharacterEncoding("utf-8");
        chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
    }

    @Override
    public void destroy() {
    }

}
package com.zemso.filter;

import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class XSSRequestWrapper extends HttpServletRequestWrapper {
    private HttpServletRequest orgRequest = null;

    public XSSRequestWrapper(HttpServletRequest request) {
        super(request);
        this.orgRequest = request;
    }

    /**
     * 覆盖getParameter方法,将参数名和参数值都做xss & sql过滤
     * 如果需要获得原始的值,则通过super.getParameterValues(name)来获
     * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
     */
    @Override
    public String getParameter(String name) {
        String[] values = this.getParameterValues(name);
        if (values == null) {
            return super.getParameter(name);
        } else {
            return values[0];
        }
    }

    @Override
    public String[] getParameterValues(String name) {
        // 通过map集合获取参数
        Map<String, String[]> map = this.getParameterMap();
        if (map == null) {
            return super.getParameterValues(name);
        } else {
            String[] strings = map.get(name);
            return strings;
        }
    }

    public Map<String, String[]> getParameterMap() {
        try {
            String method = this.orgRequest.getMethod();
            if ("post".equalsIgnoreCase(method)) {
                Map<String, String[]> request_map = super.getParameterMap();
                Iterator iterator = request_map.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry me = (Map.Entry) iterator.next();
                    System.out.println(me.getKey() + ":");
                    String[] values = (String[]) me.getValue();
                    for (int i = 0; i < values.length; i++) {
                        values[i] = xssEncode(values[i]);
                        System.out.println(values[i]);
                    }
                }
                return request_map;
            } else if ("get".equalsIgnoreCase(method)) {
                Map<String, String[]> request_map = super.getParameterMap();
                Iterator iterator = request_map.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry me = (Map.Entry) iterator.next();
                    System.out.println(me.getKey() + ":");
                    String[] values = (String[]) me.getValue();
                    for (int i = 0; i < values.length; i++) {
                        String str = new String(values[i].getBytes("iso-8859-1"), "utf-8");
                        values[i] = xssEncode(str);
                        System.out.println(values[i]);
                    }
                }
                return request_map;
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * 覆盖getHeader方法,将参数名和参数值都做xss & sql过滤。<br/>
     * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/>
     * getHeaderNames 也可能需要覆盖
     */
    @Override
    public String getHeader(String name) {
        String[] values = this.getParameterValues(name);
        if (values == null) {
            return super.getParameter(name);
        } else {
            return values[0];
        }
    }

    /**
     * 将容易引起xss & sql漏洞的半角字符直接替换成全角字符
     * 
     * @param s
     * @return
     */
    private static String xssEncode(String s) {
        if (s == null || s.isEmpty()) {
            return s;
        } else {
            s = stripXSSAndSql(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(""");// 转义双引号
                break;
            case '&':
                sb.append("&");// 转义&
                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 XSSRequestWrapper) {
            return ((XSSRequestWrapper) req).getOrgRequest();
        }

        return req;
    }

    /**
     * 
     * 防止xss跨脚本攻击(替换,根据实际情况调整)
     */

    public static String stripXSSAndSql(String value) {
        if (value != null) {
            // NOTE: It's highly recommended to use the ESAPI library and
            // uncomment the following line to
            // avoid encoded attacks.
            // value = ESAPI.encoder().canonicalize(value);
            // Avoid null characters
            /** value = value.replaceAll("", ""); ***/
            // Avoid anything between script tags
            Pattern scriptPattern = Pattern.compile(
                    "<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid anything in a
            // src="http://www.yihaomen.com/article/java/..." type of
            // e-xpression
            scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome </script> tag
            scriptPattern = Pattern.compile("</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Remove any lonesome <script ...> tag
            scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid eval(...) expressions
            scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid e-xpression(...) expressions
            scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid javascript:... expressions
            scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid vbscript:... expressions
            scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
            value = scriptPattern.matcher(value).replaceAll("");
            // Avoid onload= expressions
            scriptPattern = Pattern.compile("onload(.*?)=",
                    Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
            value = scriptPattern.matcher(value).replaceAll("");

        }
        return value;
    }

}
<filter>
        <filter-name>XssFilter</filter-name>
        <filter-class>com.zemso.filter.XSSFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>XssFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

 

posted @ 2018-10-08 14:50  WangXiaoCong  阅读(407)  评论(0编辑  收藏  举报