1. 程式人生 > >一次詭異的關於filter的問題

一次詭異的關於filter的問題

  1. 接收前臺post請求封裝的"versionDescription":"eeeeee",時,莫名傳到後臺就變成"versionDeion":"eeeeee",了。
  2. 找了半天,一直以後是前臺的問題,一直在翻閱各種js程式碼。 後來,請教大佬,大佬一聽到剛好少了script後,靈光乍現,感覺是攔截器的原因,後來查閱,果不其然。
  • 這是一個預防XSS注入的攔截器,web.xml配置如下:
    <filter>
        <filter-name>xssFilter</filter-name>
        <filter-class>com.cashew.utils.XssFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>xssFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  • 攔截器:
package com.sgcc.utils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;

public class XssFilter implements Filter {

    Logger log = Logger.getLogger(this.getClass());
    private static Pattern SCRIPT_PATTERN = Pattern
            .compile("<script.*>.*<\\/script\\s*>");
    private static Pattern HTML_PATTERN = Pattern.compile("<[^>]+>");

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest servletRequest,
            ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {
        // 獲得在下面程式碼中要用的request,response,session物件
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 設定cookie heetOnly
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            Cookie cookie = cookies[0];
            if (cookie != null) {
                // Servlet 2.5不支援在Cookie上直接設定HttpOnly屬性
                String value = cookie.getValue();
                StringBuilder builder = new StringBuilder();
                builder.append("JSESSIONID=" + value + "; ");
                builder.append("Secure; ");
                builder.append("HttpOnly; ");
                Calendar cal = Calendar.getInstance();
                cal.add(Calendar.MINUTE, 30);
                Date date = cal.getTime();
                Locale locale = Locale.CHINA;
                SimpleDateFormat sdf = new SimpleDateFormat(
                        "dd-MM-yyyy HH:mm:ss", locale);
                builder.append("Expires=" + sdf.format(date));
                response.setHeader("Set-Cookie", builder.toString());
            }
        }
                
        String method = request.getMethod();  
        if("POST".equalsIgnoreCase(method)){ 
            if (getParameterMap(request)) {
                log.info("-----檢測到危險字元,終止請求");
                response.setCharacterEncoding("UTF-8");
                response.getWriter().write(JSONObject.fromObject(getFailedMap("檢測到疑似注入操作,終止請求")).toString());
                return;
            }
        }else{
            boolean isScri = this.filterHtmlStr(request);
            boolean isSql = this.filterSql(request);
            if (!isScri || !isSql) {
                log.info("檢測到危險字元,終止請求");
                response.setCharacterEncoding("UTF-8");
                response.getWriter().write(JSONObject.fromObject(getFailedMap("檢測到疑似注入操作,終止請求")).toString());
                return;
            }
        }
        
        //chain.doFilter(servletRequest, servletResponse);  
        chain.doFilter(new XSSRequestWrapper((HttpServletRequest) servletRequest), servletResponse);
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }
    /**  
     * 方法說明 :通過獲取map的方法
     */   
    @SuppressWarnings("rawtypes")  
    private boolean getParameterMap(HttpServletRequest request) {  
        Map map = request.getParameterMap();  
        boolean illegalStr = false;  
        if (map != null) {  
            Set set = map.entrySet();  
            Iterator iterator = set.iterator();  
            while (iterator.hasNext()) {  
                Map.Entry entry = (Entry) iterator.next();  
                if (entry.getValue() instanceof String[]) {  
                    //System.out.println("==A==entry的key�? " + entry.getKey());  
                    String[] values = (String[]) entry.getValue();  
                   for (int i = 0; i < values.length; i++) {  
                       if(!entry.getKey().toString().equals("buildJsonSettings")){
                           if(!filterSqlFromSream(values[i]) || !filterHtmlStr(values[i])){
                               System.out.println("1====非法字元 key=" +entry.getKey().toString() + ";value=" + values[i]);  
                               illegalStr = true;
                               break;
                           } 
                       }
                    }
                } else if (entry.getValue() instanceof String) {  
                    if(!filterSqlFromSream(entry.getValue().toString()) || !filterHtmlStr(entry.getValue().toString())){
                         System.out.println("2====非法字元 key=" +entry.getKey().toString() + ";value=" + entry.getValue().toString());  
                         illegalStr = true;
                         break;
                     } 
                }  
            }  
        }  
        return illegalStr;  
} 
    public boolean filterHtmlStr(String inputStr) {

        Matcher mHtml = HTML_PATTERN.matcher(inputStr);
        if (mHtml.find()) {
            log.info("1------------------------Html str:" + inputStr);
            return false;
        }
        Matcher m = SCRIPT_PATTERN.matcher(inputStr);
        if (m.find()) {
            log.info("1------------------------js str:" + inputStr);
            return false;
        }
        return true;

    }

    public boolean filterHtmlStr(HttpServletRequest request) {

        Map<String, String[]> paramMap = request.getParameterMap();
        String lowStr = null;
        Set<Entry<String, String[]>> keSet = paramMap.entrySet();
        for (Iterator<Entry<String, String[]>> itr = keSet.iterator(); itr
                .hasNext();) {
            @SuppressWarnings("rawtypes")
            Map.Entry me = (Map.Entry) itr.next();
            Object ov = me.getValue();
            String[] value = new String[1];
            if (ov instanceof String[]) {
                value = (String[]) ov;
            } else {
                value[0] = ov.toString();
            }
            for (int k = 0; k < value.length; k++) {
                lowStr = value[k];
                Matcher mHtml = HTML_PATTERN.matcher(lowStr);
                if (mHtml.find()) {
                    log.info("2------------------------Html str:" + lowStr);
                    return false;
                }
                Matcher m = SCRIPT_PATTERN.matcher(lowStr);
                if (m.find()) {
                    log.info("2------------------------js str:" + lowStr);
                    return false;
                }
            }
        }
        return true;

    }

    public boolean filterSql(HttpServletRequest request) {
        Enumeration<String> params = request.getParameterNames();
        String sql = "";
        String name = "";
        while (params.hasMoreElements()) {
            name = params.nextElement().toString();
            log.info(String.format("name is [%s]", name));
            String[] value = request.getParameterValues(name);
            for (int i = 0; i < value.length; i++) {
                sql += value[i] + " ";
            }
        }
        sql = sql.toLowerCase();

        String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|chr|mid|truncate|"
                + "char|declare|sitename|net user|xp_cmdshell|or|like'|and|exec|execute|insert|create|drop|"
                + "table|from|grant|use|group_concat|column_name|"
                + "information_schema.columns|table_schema|union|where|order|by|count|*|"
                + "chr|mid|truncate|char|declare|or|like";
        String[] badStrs = badStr.split("\\|");
        String[] param = sql.split(" ");
        for (int j = 0; j < param.length; j++)
            for (int i = 0; i < badStrs.length; i++) {
                if (param[j].equalsIgnoreCase(badStrs[i])) {
                    log.info(String.format("1------------查詢到SQL注入,輸入引數:[%s]", sql));
                    return false;
                }
            }
        return true;
    }

    public boolean filterSqlFromSream(String inputJson) {
        String sql = "";
        try {
            sql = URLDecoder.decode(inputJson,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|chr|mid|truncate|"
                + "char|declare|sitename|net user|xp_cmdshell|or|like'|and|exec|execute|insert|create|drop|"
                + "table|from|grant|use|group_concat|column_name|"
                + "information_schema.columns|table_schema|union|where|order|by|count|*|"
                + "chr|mid|truncate|char|declare|or|like";
        String[] badStrs = badStr.split("\\|");
        String[] param = sql.split(" ");
        for (int j = 0; j < param.length; j++)
            for (int i = 0; i < badStrs.length; i++) {
                if (param[j].equalsIgnoreCase(badStrs[i])) {
                    log.info(String.format("2------------查詢到SQL注入,輸入引數:[%s]", sql));
                    return false;
                }
            }
        return true;
    }

    
    public String checkSpecialWord(String str) {
        return Pattern
                .compile(
                        "[`
[email protected]
#$%^&*()+=|{}':;',\\[\\].<>/?~!@#�?%…�??&*()—�??+|{}【�?��?�;:�?��?��?��?�,、?]") .matcher(str).replaceAll("").trim(); } private Map<String, String> getFailedMap(String message) { Map<String, String> ret = new HashMap<String,String>(); ret.put("status", "failed"); ret.put("message", message); return ret; } class XSSRequestWrapper extends HttpServletRequestWrapper { public XSSRequestWrapper(HttpServletRequest request) { super(request); } public String getParameter(String name) { String value = super.getParameter(name); if (value != null) { value = cleanXSS(value); } return value; } public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); if (values != null) { for (int i = 0; i < values.length; i++) { values[i] = cleanXSS(values[i]); } } return values; } private String cleanXSS(String value) { value = value.replaceAll("<", "&lt;").replaceAll(">", "&gt;"); if(value.toLowerCase().contains("<script") || value.toLowerCase().contains("</script>") ){ value = value.substring(0,value.toLowerCase().indexOf("script"))+value.substring(value.toLowerCase().indexOf("script")+6); } return value; } } }

相關推薦

詭異的關於filter的問題

接收前臺post請求封裝的"versionDescription":"eeeeee",時,莫名傳到後臺就變成"versionDeion":"eeeeee",了。 找了半天,一直以後是前臺的問題,一直在翻閱各種js程式碼。 後來,請教大佬,大佬一聽到剛好少了scri

詭異的redis連線異常

一、異常出現  啟動jar包報異常,異常資訊如下,簡單分析後初步定位為redis連線異常。 2018-10-23 15:24:00.781 ERROR kmessage [main] [org.springframework.boot.SpringApplication] - Ap

詭異的OOM坑

OOM,即OutOfMemory。作為Android裝置常見的效能問題,經常見於圖片大量載入的場景。然而博主這次碰到的OOM,卻是由一個意想不到又合情合理的問題導致。由於是半路接手一個正在開發的專案,著

詭異的git體驗-merge不生效

今天拉了個新分支,將主分支的東西拉下來時,發現merge,push,依然沒有生效 當merge不下來東西的時候,我的內心是絕望的 博智多學的蔣老師告訴我了一個方法 git 放棄本地修改,強制更新 g

"詭異"的mongodb程序退出事件

shell中通過mongo args &的方式啟動mongo程序,退出shell重新登進之後發現mongo程序沒了,檢視日誌發現有如下輸出: 2015-06-18T18:39:58.593+0800 [signalProcessingThread] g

記錄詭異的dll檔案函式問題

遇到一個很詭異的問題,記錄一下。環境win10,dell預裝的home版。自行開發的軟體a.exe,庫檔案b.dll,庫檔案c.dll由於a.exe軟體依賴的庫檔案改變了,所以重新從別人處拷貝過來程式以及依賴的庫,但是執行的時候提示[email protected]

django的詭異報錯 Could not parse the remainder: '=' from '='

django python 如題,一個展示日誌的功能,調用該模板文件時報錯,Could not parse the remainder: ‘=‘ from ‘=‘。這行模板語言在上面出現過同樣的,僅僅是改了‘<=‘右端的整數大小,而且該有的標簽也不少。百般思考無解,stackoverflow和百

打包的詭異現象

被拒絕 工具 它的 oot mic 詭異 運行 出錯 mon 一、前情提要:   今天線上打包,發現啟動正常,但是訪問異常,看日誌也沒有打印出什麽異常信息。   更新的微服務包訪問的時候一直報出【403】,訪問被拒   項目架構:springBoot + mave

SpringBoot 配置檔案未生效和war包執行失敗one or more listener(filter)。。。

從SVN上扒下來的專案,上傳者正常啟動正常使用,配置檔案port修改為80 但自己本機拿下來以後未生效 還是隻能以8080訪問  還報了模版解析錯誤等等...  按如上修改  手動對映一下就可以了 未載入properties是因為未指定resource

Redis記憶體詭異增長

  一、現象 例項名:r-bp1cxxxxxxxxxd04(主從) 時間:2017-11-16 12:26~12:27 問題:一分鐘記憶體上漲了2G,如下圖所示: 鍵值規模:6000萬左右 二、Redis記憶體分析 1.記憶體組成 上圖中的記憶體統計的是Re

圖片的每點選旋轉90度, filter和css3屬性

<!DOCTYPE html> <html>     <head>         <title> ImageRotation </title>         <meta http-equiv="Conte

mapreduce讀取不到輸入文件的問題

mapreduce 過濾器hdfs上輸入文件所在包含兩個目錄,分別是: /20170503/shoplast/ /20170503/shop/但是我想過濾掉shop,只把shoplast作為輸入故我實現了過濾器如下: public static class Fi

SAP query傳輸以後須要又生成程序

stand 發現 div 控件 沒變化 通過 們的 本地 environ 近期有個需求,須要改動一個Query,在DEV改動好並測試通過後。傳輸到QAS,可是報表還是沒變化,著實郁悶了一下,這是萬能的google幫上忙了,原來傳到其它系統以後還須要generate pr

Android有關surfaceView又創建的問題。

視頻播放器 android pan layer 狀態 style 又一 一次 space 近期在做一個Android視頻播放器的項目。遇到一個問題,就是鎖屏之後。surfaceview就會被銷毀掉,然後就會出現各種錯誤。到csdn論壇去發帖提問,各種所謂的大神都說,解鎖

想不到的Spring事務失效問題跟蹤(事務不會滾)

spring srpingjdbc srpingtx 周末,鼓搗了下spring事務。spring事務配置其實很簡單,這是spring優點。但問題是,不知道其中原理,遇到點問題,就抓瞎了。我就犯傻了一次。在追蹤問題時,搜索到的答案,主要有以下幾類。springmvc 上下文,與service上下文

完成的簡單監控配置

一次完成的簡單監控配置一次完成的簡單監控配置:host group --> host --> [application] --> item --> trigger(Events) -->(Media Type,User Group,User) --> action(cond

XMLHttpRequest是什麽、如何完整地運行GET請求、如何檢測錯誤。

var obj problem get請求 () == name xmlhttp 如何 var xmlhttp; function LoadXmlDoc(url){

關於勒索病毒 Ransom:Win32.WannaCrypt 解決方案的最後說明

勒索軟件關於勒索病毒 Ransom:Win32.WannaCrypt 解決方案的最後一次說明2017/5/12 晚,勒索軟件 Ransom:Win32.WannaCrypt 大面積暴發。比病毒爆發更火的,則是各類關於此病毒的新聞、解決方法等在朋友圈等社交媒體的爆發。其中,有主觀善意客觀一知半解的知道,更有夾帶

Unite'17 Shanghai再問候

經理 動畫 nal 會議 公司 遊戲開發 一場 未來 family Unite‘17 Shanghai再一次問候 --暨Unity2017年度大會 2017年5月11日,主題為“再一次問候”的Unity年度盛會在上海國際會議中心舉行,這是Unity繼GDC

阿裏電面經歷

art 存儲空間 自由 結束 eas 大型 特定 easy col 昨天下午(3/19)三點多鐘,接到了一個杭州的電話,是阿裏的。問我是否方便聊聊。我說我在上課,四點下課。然後他就四點多鐘的時候又打了一次過來。項目經歷上來就問我有無大型項目的經歷。不好意思,我說無。。。又