xss攻擊防禦springMVC表單提交數據過濾/轉義

Markdown及擴展

背景1:spring中的filter攔截request中請求入參,但對於post提交的表單無效
背景2:測試工具firefox的hackbar,postData:idNum=idNum=14043’%3bconfirm(1)%2f%2f846&seNo=&clientName=

代碼塊

前端代碼:

<form action="${path}/test" id="selectForm" method="post">
         <input type="hidden" id="idNum" name="idNum" value="${idNum}"/>
         <input type="hidden" id="seNo" name="seNo" value="${seNo}"/>
         <input type="hidden" id="clientName" name="clientName" value="${clientName}"/>
</form>

後端代碼:

    @RequestMapping(value = "/test",method = RequestMethod.POST)
    @ResponseBody
    public ModelAndView fill(@RequestParam(value = "idNum", required = false) String idNum,
            @RequestParam(value = "seNo", required = false) String seNo,
            @RequestParam(value = "clientName", required = false) String clientName) {
        ModelAndView view = new ModelAndView("/claims/claimsfill");
        view.addObject("idNum",idNum);
        view.addObject("seNo",seNo);
        view.addObject("clientName",clientName);
        return view;
    }

過濾器:

import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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

import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

public class XSSFilter extends OncePerRequestFilter {
    public void setExclude(String exclude) {
        this.exclude = exclude;
        pattern = Pattern.compile(getRegStr(exclude));
    }
    /**
     * XSS過濾
     */
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String requestURI = request.getRequestURI();
        if(StringUtils.isNotBlank(requestURI))
            requestURI = requestURI.replace(request.getContextPath(),"");
            EscapeScriptwrapper escapeScriptwrapper = new EscapeScriptwrapper(request);
            filterChain.doFilter(escapeScriptwrapper, response);
    }

    /**
     * 將傳遞進來的不需要過濾得路徑集合的字符串格式化成一系列的正則規則
     * @param str 不需要過濾的路徑集合
     * @return 正則表達式規則
     * */
    private String getRegStr(String str){
        if(StringUtils.isNotBlank(str)){
            String[] excludes = str.split(";");  //以分號進行分割
            int length = excludes.length;
            for(int i=0;i<length;i++){
                String tmpExclude = excludes[i];
                //對點、反斜槓和星號進行轉義
                tmpExclude = tmpExclude.replace("\\", "\\\\").replace(".", "\\.").replace("*", ".*");

                tmpExclude = "^" + tmpExclude + "$";
                excludes[i] = tmpExclude;
            }
            return StringUtils.join(excludes, "|");
        }
        return str;
    }

    /**
     * 繼承HttpServletRequestWrapper,創建裝飾類,以達到修改HttpServletRequest參數的目的
     * */
    private class EscapeScriptwrapper extends HttpServletRequestWrapper{
        private Map<String, String[]> parameterMap;  //所有參數的Map集合
        public EscapeScriptwrapper(HttpServletRequest request) {
            super(request);
            parameterMap = request.getParameterMap();
        }

        //重寫幾個HttpServletRequestWrapper中的方法
        /**
         * 獲取所有參數名
         * @return 返回所有參數名
         * */
        @Override
        public Enumeration<String> getParameterNames() {
            Vector<String> vector = new Vector<String>(parameterMap.keySet());
            return vector.elements();
        }

        /**
         * 獲取指定參數名的值,如果有重複的參數名,則返回第一個的值
         * 接收一般變量 ,如text類型
         * 
         * @param name 指定參數名
         * @return 指定參數名的值
         * */
        @Override
        public String getParameter(String name) {
            String[] results = parameterMap.get(name);
            if(results == null || results.length <= 0)
                return null;
            else{
                return escapeXSS(results[0]);
            }
        }

        /**
         * 獲取指定參數名的所有值的數組,如:checkbox的所有數據
         * 接收數組變量 ,如checkobx類型
         * */
        @Override
        public String[] getParameterValues(String name) {
            String[] results = parameterMap.get(name);
            if(results == null || results.length <= 0)
                return null;
            else{
                int length = results.length;
                for(int i=0;i<length;i++){
                    results[i] = escapeXSS(results[i]);
                }
                return results;
            }
        }

        /**
         * 過濾字符串中的js腳本
         * 解碼:StringEscapeUtils.unescapeXml(escapedStr)
         * */
        private String escapeXSS(String str){
            str = StringEscapeUtils.escapeXml(str);

            Pattern tmpPattern = Pattern.compile("[sS][cC][rR][iI][pP][tT]");
            Matcher tmpMatcher = tmpPattern.matcher(str);
            if(tmpMatcher.find()){
                str = tmpMatcher.replaceAll(tmpMatcher.group(0) + "\\\\");
            }
            return str;
        }
    }

}

web.xml:

<filter>
    <filter-name>xssFilter</filter-name>
    <filter-class>com.ahut.ngsp.insite.filter.XSSFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>xssFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章