防止网站遭受恶意脚本攻击


import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

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


/**
 * @date
 * @describe request信息封装类,用于判断、处理request请求中特殊字符
 */
public class XSSHttpRequestWrapper extends HttpServletRequestWrapper {
    
    /**
     * 封装http请求
     * @param request
     */
    public XSSHttpRequestWrapper(HttpServletRequest request) {
        super(request);
    }
    
    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        // 若开启特殊字符替换,对特殊字符进行替换
        if(XSSSecurityConfig.REPLACE){
            XSSSecurityManager.securityReplace(name);
        }
        return value;
    }

    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        // 若开启特殊字符替换,对特殊字符进行替换
        if(XSSSecurityConfig.REPLACE){
            XSSSecurityManager.securityReplace(name);
        }
        return value;
    }

    /**
     * 没有违规的数据,就返回false;
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    private boolean checkHeader(){
        Enumeration<String> headerParams = this.getHeaderNames();
        while(headerParams.hasMoreElements()){
            String headerName = headerParams.nextElement();
            String headerValue = this.getHeader(headerName);
            if(XSSSecurityManager.matches(headerValue)){
                return true;
            }
        }
        return false;
    }
    
    /**
     * 没有违规的数据,就返回false;
     *
     * @return
     */
    @SuppressWarnings("unchecked")
    private boolean checkParameter(){
        Map<String,Object> submitParams = this.getParameterMap();
        Set<String> submitNames = submitParams.keySet();
        for(String submitName : submitNames){
            Object submitValues = submitParams.get(submitName);
            if(submitValues instanceof String){
                if(XSSSecurityManager.matches((String)submitValues)){
                    return true;
                }
            }else if(submitValues instanceof String[]){
                for(String submitValue : (String[])submitValues){
                    if(XSSSecurityManager.matches((String)submitValue)){
                        return true;
                    }
                }
            }
        }
        return false;
    }
    
   
    /**
     * 没有违规的数据,就返回false;
     * 若存在违规数据,根据配置信息判断是否跳转到错误页面
     * @param response
     * @return
     * @throws IOException
     * @throws ServletException
     */
    public boolean validateParameter(HttpServletResponse response) throws ServletException, IOException{
        // 开始header校验,对header信息进行校验
        if(XSSSecurityConfig.IS_CHECK_HEADER){
            if(this.checkHeader()){
                return true;
            }
        }
        // 开始parameter校验,对parameter信息进行校验
        if(XSSSecurityConfig.IS_CHECK_PARAMETER){
            if(this.checkParameter()){
                return true;
            }
        }
        return false;
    }
    
}




/**
 * @date
 * @describe
 */
public class XSSSecurityCon {

    /**
     * 配置文件标签 isCheckHeader
     */
    public static String IS_CHECK_HEADER = "isCheckHeader";

    /**
     * 配置文件标签 isCheckParameter
     */
    public static String IS_CHECK_PARAMETER = "isCheckParameter";

    /**
     * 配置文件标签 isLog
     */
    public static String IS_LOG = "isLog";

    /**
     * 配置文件标签 isChain
     */
    public static String IS_CHAIN = "isChain";

    /**
     * 配置文件标签 replace
     */
    public static String REPLACE = "replace";

    /**
     * 配置文件标签 regexList
     */
    public static String REGEX_LIST = "regexList";

    /**
     * 替换非法字符的字符串
     */
    public static String REPLACEMENT = "";

    /**
     * FILTER_ERROR_PAGE:过滤后错误页面
     */
    public static String FILTER_ERROR_PAGE = "filterErrorPage";

}




/**
 * 安全过滤配置信息类
 */
public class XSSSecurityConfig {
    
    /**
     * CHECK_HEADER:是否开启header校验
     */
    public static boolean IS_CHECK_HEADER;
    
    /**
     * CHECK_PARAMETER:是否开启parameter校验
     */
    public static boolean IS_CHECK_PARAMETER;
    
    /**
     * IS_LOG:是否记录日志
     */
    public static boolean IS_LOG;
    
    /**
     * IS_LOG:是否中断操作
     */
    public static boolean IS_CHAIN;
    
    /**
     * REPLACE:是否开启替换
     */
    public static boolean REPLACE;
    
    /**
     * FILTER_ERROR_PAGE:过滤后错误页面
     */
    public static String FILTER_ERROR_PAGE;
    

}



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 javax.servlet.http.HttpServletResponse;
/**
 * @date
 * @describe 安全信息审核类
 */
public class XSSSecurityFilter implements Filter{
    public XSSSecurityFilter() {
        // TODO Auto-generated constructor stub
    }
    
    /**
     * 销毁操作
     */
    public void destroy() {
        //System.out.println("XSSSecurityFilter destroy() begin");
        XSSSecurityManager.destroy();
        //System.out.println("XSSSecurityFilter destroy() end");
    }

    /**
     * 安全审核
     * 读取配置信息
     */
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        // 判断是否使用HTTP
        checkRequestResponse(request, response);
        // 转型
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        // http信息封装类
        XSSHttpRequestWrapper xssRequest = new XSSHttpRequestWrapper(httpRequest);
        
        // 对request信息进行封装并进行校验工作,若校验失败(含非法字符),根据配置信息进行日志记录和请求中断处理
        if(xssRequest.validateParameter(httpResponse)){
            if(XSSSecurityConfig.IS_LOG){
                // 记录攻击访问日志
                // 可使用数据库、日志、文件等方式
            }
            if(XSSSecurityConfig.IS_CHAIN){
                httpRequest.getRequestDispatcher(XSSSecurityConfig.FILTER_ERROR_PAGE).forward( httpRequest, httpResponse);
                return;
            }
        }
        chain.doFilter(xssRequest, response);
    }

    /**
     * 初始化操作
     */
    public void init(FilterConfig filterConfig) throws ServletException {
        //System.out.println("-------init()-------");
        XSSSecurityManager.init(filterConfig);
    }

    /**
     * 判断Request ,Response 类型
     * @param request
     *            ServletRequest
     * @param response
     *            ServletResponse
     * @throws ServletException
     */
    private void checkRequestResponse(ServletRequest request,
            ServletResponse response) throws ServletException {
        if (!(request instanceof HttpServletRequest)) {
            throw new ServletException("Can only process HttpServletRequest");

        }
        if (!(response instanceof HttpServletResponse)) {
            throw new ServletException("Can only process HttpServletResponse");
        }
    }
}



import java.util.Iterator;
import java.util.regex.Pattern;

import javax.servlet.FilterConfig;

import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * @date
 * @describe 安全过滤配置管理类,由XSSSecurityManger修改
 */
public class XSSSecurityManager {
    
    //private static Logger logger = Logger.getLogger(XSSSecurityManager.class);
    
    /**
     * REGEX:校验正则表达式
     */
    public static String REGEX;
    
     /**
     * 特殊字符匹配
     */
    private static Pattern XSS_PATTERN ;
    
    
    private XSSSecurityManager(){
        //不可被实例化
    }
    
    public static void init(FilterConfig config){
//        System.out.println("XSSSecurityManager init(FilterConfig config) begin");
        //初始化过滤配置文件
        String xssPath = config.getServletContext().getRealPath("/")
                + config.getInitParameter("securityconfig");
        
        //String xssPath="F:\\site\\xsssecurity\\WEB-INF\\classes\\xss_security_config.xml";
        
//        System.out.println("路径:"+xssPath);
        // 初始化安全过滤配置
        try {
            if(initConfig(xssPath)){
                // 生成匹配器
                XSS_PATTERN = Pattern.compile(REGEX);
            }
        } catch (DocumentException e) {
            //logger.error("安全过滤配置文件xss_security_config.xml加载异常",e);
//            System.out.println("安全过滤配置文件xss_security_config.xml加载异常");
        }
        //logger.info("XSSSecurityManager init(FilterConfig config) end");
//        System.out.println("XSSSecurityManager init(FilterConfig config) end");
    }
    
    /**
     * 读取安全审核配置文件xss_security_config.xml
     * 设置XSSSecurityConfig配置信息
     * @param path 配置文件地址 eg C:/apache-tomcat-6.0.33/webapps/security_filter/WebRoot/config/xss/xss_security_config.xml
     * @return
     * @throws DocumentException
     */
    @SuppressWarnings("unchecked")
    public static boolean initConfig(String path) throws DocumentException {
//        logger.info("XSSSecurityManager.initConfig(String path) begin");
//        System.out.println("XSSSecurityManager.initConfig(String path) begin");
        Element superElement = new SAXReader().read(path).getRootElement();
        XSSSecurityConfig.IS_CHECK_HEADER = new Boolean(getEleValue(superElement,XSSSecurityCon.IS_CHECK_HEADER));
        XSSSecurityConfig.IS_CHECK_PARAMETER = new Boolean(getEleValue(superElement,XSSSecurityCon.IS_CHECK_PARAMETER));
        XSSSecurityConfig.IS_LOG = new Boolean(getEleValue(superElement,XSSSecurityCon.IS_LOG));
        XSSSecurityConfig.IS_CHAIN = new Boolean(getEleValue(superElement,XSSSecurityCon.IS_CHAIN));
        XSSSecurityConfig.REPLACE = new Boolean(getEleValue(superElement,XSSSecurityCon.REPLACE));
        XSSSecurityConfig.FILTER_ERROR_PAGE = getEleValue(superElement,XSSSecurityCon.FILTER_ERROR_PAGE);

        Element regexEle = superElement.element(XSSSecurityCon.REGEX_LIST);
        
        if(regexEle != null){
            Iterator<Element> regexIt = regexEle.elementIterator();
            StringBuffer tempStr = new StringBuffer("^");
            //xml的cdata标签传输数据时,会默认在\前加\,需要将\\替换为\
            while(regexIt.hasNext()){
                Element regex = (Element)regexIt.next();
                String tmp = regex.getText();
                tmp = tmp.replaceAll("\\\\\\\\", "\\\\");
                tempStr.append(tmp);
                tempStr.append("|");
            }
            if(tempStr.charAt(tempStr.length()-1)=='|'){
                REGEX= tempStr.substring(0, tempStr.length()-1)+"$";
                //logger.info("安全匹配规则"+REGEX);
//                System.out.println("安全匹配规则"+REGEX);
            }else{
                //logger.error("安全过滤配置文件加载失败:正则表达式异常 "+tempStr.toString());
//                System.out.println("安全过滤配置文件加载失败:正则表达式异常 ");
                return false;
            }
        }else{
            //logger.error("安全过滤配置文件中没有 "+XSSSecurityCon.REGEX_LIST+" 属性");
//            System.out.println("安全过滤配置文件中没有 "+XSSSecurityCon.REGEX_LIST+" 属性");
            return false;
        }
        //logger.info("XSSSecurityManager.initConfig(String path) end");
//        System.out.println("XSSSecurityManager.initConfig(String path) end");
        return true;

    }
    
    /**
     * 从目标element中获取指定标签信息,若找不到该标签,记录错误日志
     * @param element 目标节点
     * @param tagName 制定标签
     * @return
     */
    private static String getEleValue(Element element, String tagName){
        if (isNullStr(element.elementText(tagName))){
            //logger.error("安全过滤配置文件中没有 "+XSSSecurityCon.REGEX_LIST+" 属性");
//            System.out.println("安全过滤配置文件中没有 "+XSSSecurityCon.REGEX_LIST+" 属性");
        }
        return element.elementText(tagName);
    }
    
    /**
     * 对非法字符进行替换
     * @param text
     * @return
     */
    public static String securityReplace(String text){
//        System.out.println("对非法字符进行替换");
        if(isNullStr(text)){
//            System.out.println("if:---"+text);
            return text;
        }else{
//            System.out.println("else:---"+text.replaceAll(REGEX, XSSSecurityCon.REPLACEMENT));
            return text.replaceAll(REGEX, XSSSecurityCon.REPLACEMENT);
        }
    }
    
    /**
     * 匹配字符是否含特殊字符
     * @param text
     * @return
     */
    public static boolean matches(String text){
//        System.out.println("匹配字符是否含特殊字符");
        if(text==null){
            return false;
        }
        return XSS_PATTERN.matcher(text).matches();
    }
    
    /**
     * 释放关键信息
     */
    public static void destroy(){
//        logger.info("XSSSecurityManager.destroy() begin");
//        System.out.println("XSSSecurityManager.destroy() begin");
        XSS_PATTERN = null;
        REGEX = null;
//        logger.info("XSSSecurityManager.destroy() end");
//        System.out.println("XSSSecurityManager.destroy() end");
    }
    
    /**
     * 判断是否为空串,建议放到某个工具类中
     * @param value
     * @return
     */
    public static boolean isNullStr(String value){
        return value == null || value.trim().equals("");
    }
}

xss_security_config.xml

<?xml version="1.0" encoding="UTF-8"?>
<XSSConfig>
    <!-- 是否进行header校验 -->
    <isCheckHeader>true</isCheckHeader>
    <!-- 是否进行parameter校验 -->
    <isCheckParameter>true</isCheckParameter>
    <!-- 是否记录日志 -->
    <isLog>false</isLog>
    <!-- 是否中断请求 -->
    <isChain>true</isChain>
    <!-- 是否开启特殊字符替换 -->
    <replace>true</replace>
    <!-- 是否开启特殊url校验 -->
    <isCheckUrl>true</isCheckUrl>
    <!-- 过滤后错误页面,是否中断请求为真时有效 -->
    <filterErrorPage>/filtererror.jsp</filterErrorPage>
    <regexList>
        <!-- 匹配含有字符: alert( ) -->
        <regex><![CDATA[.*[A|a][L|l][E|e][R|r][T|t]\\s*\\(.*\\).*]]></regex>
        <!-- 匹配含有字符: window.location = -->
        <regex><![CDATA[.*[W|w][I|i][N|n][D|d][O|o][W|w]\\.[L|l][O|o][C|c][A|a][T|t][I|i][O|o][N|n]\\s*=.*]]></regex>
        <!-- 匹配含有字符:style = x:ex pression ( ) -->
        <regex><![CDATA[.*[S|s][T|t][Y|y][L|l][E|e]\\s*=.*[X|x]:[E|e][X|x].*[P|p][R|r][E|e][S|s]{1,2}[I|i][O|o][N|n]\\s*\\(.*\\).*]]></regex>
        <!-- 匹配含有字符: document.cookie -->
        <regex><![CDATA[.*[D|d][O|o][C|c][U|u][M|m][E|e][N|n][T|t]\\.[C|c][O|o]{2}[K|k][I|i][E|e].*]]></regex>
        <!-- 匹配含有字符: eval( ) -->
        <regex><![CDATA[.*[E|e][V|v][A|a][L|l]\\s*\\(.*\\).*]]></regex>
        <!-- 匹配含有字符: unescape() -->
        <regex><![CDATA[.*[U|u][N|n][E|e][S|s][C|c][A|a][P|p][E|e]\\s*\\(.*\\).*]]></regex>
        <!-- 匹配含有字符: execscript( ) -->
        <regex><![CDATA[.*[E|e][X|x][E|e][C|c][S|s][C|c][R|r][I|i][P|p][T|t]\\s*\\(.*\\).*]]></regex>
        <!-- 匹配含有字符: msgbox( ) -->
        <regex><![CDATA[.*[M|m][S|s][G|g][B|b][O|o][X|x]\\s*\\(.*\\).*]]></regex>
        <!-- 匹配含有字符: confirm( ) -->
        <regex><![CDATA[.*[C|c][O|o][N|n][F|f][I|i][R|r][M|m]\\s*\\(.*\\).*]]></regex>
        <!-- 匹配含有字符: prompt( ) -->
        <regex><![CDATA[.*[P|p][R|r][O|o][M|m][P|p][T|t]\\s*\\(.*\\).*]]></regex>
        <!-- 匹配含有字符: <script> </script> or </script> -->
        <regex><![CDATA[.*<[B|b][O|o][D|d][Y|y].*>.*|.*</[B|b][O|o][D|d][Y|y].*>.*|.*<[S|s][C|c][R|r][I|i][P|p][T|t].*>.*|.*<[S|s][C|c][R|r][I|i][P|p][T|t]>.*</[S|s][C|c][R|r][I|i][P|p][T|t]>.*|.*</[S|s][C|c][R|r][I|i][P|p][T|t]>.*]]></regex>
        <!-- 匹配含有字符: 含有一个符号: "  -->
        <regex><![CDATA[[.&[^\"]]*\"[.&[^\"]]*]]></regex>
        <!-- 匹配含有字符: 含有一个符号: '  -->
        <regex><![CDATA[[.&[^']]*'[.&[^']]*]]></regex>
        <!-- 匹配含有字符:<title></title> -->
        <regex><![CDATA[.*<[T|t][I|i][T|t][L|l][E|e].*>.*|.*</[T|t][I|i][T|t][L|l][E|e]>.*]]></regex>
        <!-- 匹配含有字符: 含有回车换行 和 <script> </script> -->
        <regex><![CDATA[[[.&[^a]]|[|a|\n|\r\n|\r|\u0085|\u2028|\u2029]]*<[S|s][C|c][R|r][I|i][P|p][T|t]>.*</[S|s][C|c][R|r][I|i][P|p][T|t]>[[.&[^a]]|[|a|\n|\r\n|\r|\u0085|\u2028|\u2029]]*]]></regex>
    </regexList>
</XSSConfig>

发布了109 篇原创文章 · 获赞 17 · 访问量 31万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章