溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot中怎么使用過濾器以及jsoup過濾XSS腳本怎么寫

發布時間:2021-12-18 14:52:09 來源:億速云 閱讀:188 作者:柒染 欄目:開發技術

springboot中怎么使用過濾器以及jsoup過濾XSS腳本怎么寫,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

    springboot使用過濾器,jsoup過濾XSS腳本

    背景:略

    目標:完成request請求中的腳本過濾

    技術:filter,jsoup,requestWapper

    1.把可能包含腳本的參數位置分析一下

    • post/put/delete: 請求的參數中,有可能是表單提交、也有可能是使用了@requestBody注解,那么參數就是json格式,位于request的流中。

    • get/options等:可能存在于url參數中,也有可能是表單提交的預請求中,所以一般在能想到的位置都有可能存在,包括header中。

    2.分析實現過程

    2.1首先要從request請求中將各個需要過濾位置的參數取出來

    2.2然后將參數取出來進行過濾

    2.3將過濾后的參數重新包裝成request傳遞下去

    2.4在這期間,

    • 需要準備好jsoup過濾腳本的工具類;

    • 需要自定義一個過濾器,并且在過濾器中添加匹配條件,如:那些url不需要過濾,那些請求方式必須進行過濾;

    • 對過濾器進行配置,是否開啟,設置在整個過濾器鏈中的位置,設置過濾的白名單或者黑名單

    • 所以就很清晰了我們過濾需要哪些類,哪些配置了

    一個filter

    一個requestWapper

    一個jsoup工具類

    一個filter的配置類

    2.5進行數據測試

    3.代碼實現過程

    3.1.jsoup依賴:

    <!--screen xss --> 
    <dependency> 
    <groupId>org.jsoup</groupId> 
    <artifactId>jsoup</artifactId> 
    <version>1.9.2</version> 
    </dependency>

    3.2jsoup工具類:JsoupUtil

    import org.jsoup.Jsoup; 
    import org.jsoup.nodes.Document; 
    import org.jsoup.safety.Whitelist;   
    import java.io.FileNotFoundException; 
    import java.io.IOException;  
     
    /**
    * @Auther: qianshanmuxue
    * @Date: 2019/2/27 19:32
    * @Description: xss Illegal label filtering
    */
     
    public class JsoupUtil {   
    private static final Whitelist whitelist = Whitelist.simpleText();//jsoup白名單種類,有四種,每一種針對的標簽類型不一樣,具體的可以ctrl+左鍵點擊simpleText,在jsoup源碼中有響應的注釋和標簽名單
    //add myself white list label
    private static final Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);
    static {
    whitelist.addAttributes(":all", "style").addTags("p").addTags("strong");//將自定義標簽添加進白名單,除開白名單之外的標簽都會被過濾
    whitelist.preserveRelativeLinks(true);//這個配置的意思的過濾如果找不到成對的標簽,就只過濾單個標簽,而不用把后面所有的文本都進行過濾。
    //(之前在這個問題上折騰了很久,當<script>標簽只有一個時,會<script>標簽后面的數據全部過濾)
    }
     
    public static String clean(String content) { //過濾方法
    return Jsoup.clean(content, "", whitelist, outputSettings);
    }
     
    //test main
    public static void main(String[] args) throws FileNotFoundException, IOException {
    String text = "<a href=\"http://www.baidu.com/a\" onclick=\"alert(1);\"><strong><p>sss</p></strong></a><script>alert(0);</script>sss";
    System.out.println(clean(text));
    }
    }

    3.3request包裝類XssHttpServletRequestWrapper

    import java.io.*;
    import java.util.*;
    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import com.xxx.utils.JsoupUtil;
    import org.jsoup.nodes.Document;
    import org.springframework.util.StringUtils;
     
    /**
     * @Auther: qianshanmuxue
     * @Date: 2019/2/27 16:24
     * @Description:request wapper use to get request parameter and request bdoy data and wapper another request 
     */
    public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { //因為我們需要獲取request中的數據,所以需要繼承java底層中HttpServletRequestWrapper這個類,重寫父類中的某些方法,獲取相應位置的參數
        private HttpServletRequest orgRequest = null;
        private static final Document.OutputSettings outputSettings = new Document.OutputSettings().prettyPrint(false);
        public XssHttpServletRequestWrapper(HttpServletRequest request) {
            super(request);
            orgRequest = request;
        }
     
        @Override 
        public ServletInputStream getInputStream() throws IOException {//get  
            BufferedReader br = new BufferedReader(new InputStreamReader(orgRequest.getInputStream()));
            String line = br.readLine();
            String result = "";
            if (line != null) {
                result += clean(line);
            } 
            return new WrappedServletInputStream(new ByteArrayInputStream(result.getBytes()));
        }
        @Override
        public String getParameter(String name) {
            if (("content".equals(name) || name.endsWith("WithHtml"))) {
                return super.getParameter(name);
            }
            name = clean(name);
            String value = super.getParameter(name);
            if (!StringUtils.isEmpty(value)) {
                value = clean(value);
            }
            return value;
        }
     
        @Override
        public Map getParameterMap() {
            Map map = super.getParameterMap();
            // 返回值Map
            Map<String, String> returnMap = new HashMap<String, String>();
            Iterator entries = map.entrySet().iterator();
            Map.Entry entry;
            String name = "";
            String value = "";
            while (entries.hasNext()) {
                entry = (Map.Entry) entries.next();
                name = (String) entry.getKey();
                Object valueObj = entry.getValue();
                if (null == valueObj) {
                    value = "";
                } else if (valueObj instanceof String[]) {
                    String[] values = (String[]) valueObj;
                    for (int i = 0; i < values.length; i++) {
                        value = values[i] + ",";
                    }
                    value = value.substring(0, value.length() - 1);
                } else {
                    value = valueObj.toString();
                }
                returnMap.put(name, clean(value).trim());
            }
            return returnMap;
        }
     
        @Override
        public String[] getParameterValues(String name) {
            String[] arr = super.getParameterValues(name);
            if (arr != null) {
                for (int i = 0; i < arr.length; i++) {
                    arr[i] = clean(arr[i]);
                }
            }
            return arr;
        }
     
        /**
         * get org request
         *
         * @return
         */
        public HttpServletRequest getOrgRequest() {
            return orgRequest;
        }
     
        /**
         * wapper request
         */
        public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
            if (req instanceof XssHttpServletRequestWrapper) {
                return ((XssHttpServletRequestWrapper) req).getOrgRequest();
            }
            return req;
        }
     
        public String clean(String content) {
            String result = JsoupUtil.clean(content);
            return result;
        }
     
        private class WrappedServletInputStream extends ServletInputStream {
            public void setStream(InputStream stream) {
                this.stream = stream;
            }
     
            private InputStream stream; 
            public WrappedServletInputStream(InputStream stream) {
                this.stream = stream;
            }
     
            @Override
            public int read() throws IOException {
                return stream.read();
            }
     
            @Override
            public boolean isFinished() {
                return true;
            }
     
            @Override
            public boolean isReady() {
                return true;
            }
     
            @Override
            public void setReadListener(ReadListener readListener) { 
            }
        }
    }

    3.4filter-XssFilter

    import org.apache.commons.lang.BooleanUtils;
    import org.apache.commons.lang.StringUtils; 
    import java.io.IOException; 
    import java.util.ArrayList;
    import java.util.List;
    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.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    /**
     * @Auther: qianshanmuxue
     * @Date: 2019/2/27 16:25
     * @Description:
     */
    //@WebFilter
    //@Component   在這里可以不用這個注解,以為后面我們會在config中去配置這個filter,在這里只需要實現 Filter  接口實現相應的方法就ok
    public class XssFilter implements Filter {
        private static boolean IS_INCLUDE_RICH_TEXT = false;//用于接收配置中的參數,決定這個過濾器是否開啟
        public List<String> excludes = new ArrayList<String>();//用于接收配置中的參數,決定哪些是不需要過濾的url(在這里,也可以修改handleExcludeURL()方法中相應的代碼,使其變更為只需要過濾的url)
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse resp = (HttpServletResponse) response;
            if (handleExcludeURL(req, resp)) {
                chain.doFilter(request, response);
                return;
            }
            XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
            chain.doFilter(xssRequest, response);
        }
    /**
    *此方法是決定對當前url是否執行過濾,
    *在這里沒有使用請求方法(post/put)來匹配,因為在本項目中使用url匹配更適合(因為get和其他請求方式也需要進行過濾),如果你有興趣可以把這個方法更改為匹配請求方法進行過濾
    **/
        private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response) {
            if ((excludes == null || excludes.isEmpty())&&IS_INCLUDE_RICH_TEXT) {
                return false;
            }
            String url = request.getServletPath();
            for (String pattern : excludes) {
                Pattern p = Pattern.compile("^" + pattern);
                Matcher m = p.matcher(url);
                if (m.find()) {
                    return true;
                }
            }
            return false;
        }
    /**
     *過濾器初始化,從配置類中獲取參數,用于初始化兩個參數(是否開啟,排除指定的url list)
     *
     */
        @Override
        public void init(FilterConfig arg0) throws ServletException {
            String isIncludeRichText = arg0.getInitParameter("isIncludeRichText");
            if (StringUtils.isNotBlank(isIncludeRichText)) {
                IS_INCLUDE_RICH_TEXT = BooleanUtils.toBoolean(isIncludeRichText);
            }
     
            String temp = arg0.getInitParameter("excludes");
            if (temp != null) {
                String[] url = temp.split(",");
                for (int i = 0; url != null && i < url.length; i++) {
                    excludes.add(url[i]);
                }
            }
        }
     
        @Override
        public void destroy() {
        }
    }

    3.5filter的配置類:XssConfig

    import com.xxx.filter.XssFilter;
    import com.google.common.collect.Maps;
    import org.springframework.boot.web.servlet.FilterRegistrationBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration; 
    import java.util.Map;
     
    /**
     * @Auther: qianshanmuxue
     * @Date: 2019/2/27 16:49
     * @Description: xss filter config
     */
    @Configuration
    public class XssConfig {
        @Bean
        public FilterRegistrationBean xssFilterRegistrationBean() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
            filterRegistrationBean.setFilter(new XssFilter());
            filterRegistrationBean.setOrder(1);//filter order ,set it first
            filterRegistrationBean.setEnabled(true);
            filterRegistrationBean.addUrlPatterns("/*"); //set filter all url mapping
            Map<String, String> initParameters = Maps.newHashMap();
            initParameters.put("excludes", "/oauth/token");///white list url
            initParameters.put("isIncludeRichText", "true");//enable or disable
            filterRegistrationBean.setInitParameters(initParameters);
            return filterRegistrationBean;
        }
    }

    調試截圖:

    請求:

    springboot中怎么使用過濾器以及jsoup過濾XSS腳本怎么寫

    程序截圖:

    springboot中怎么使用過濾器以及jsoup過濾XSS腳本怎么寫

    運行結果:

    springboot中怎么使用過濾器以及jsoup過濾XSS腳本怎么寫

    可以看到body中 的腳本已經被過濾了,

    然后其他的截圖我就不發了,還有一種思路就是在過濾器中把字符轉義。

    感謝luckpet大佬的提示

    1 BufferedReader 使用完需要關閉 ;

    2 對于一些拿postman等工具的朋友,拼接json的話會有換行 這里result += clean(line); 需要改成: while((line = br.readLine()) != null){ if (line != null) { result += line; } }

    使用jsoup防止XSS攻擊

    前陣子項目國測后,打開一個項目頁面,莫名其妙彈出xss,搜了全局也沒找到alert("xss"),問了一下項目經理,原來是國測做防注入的時候,在添加數據的時候做的,一臉懵逼。

    查了一下資料,以前做項目的時候都沒想到這個問題,如果保存一段script腳本,查數據的時候,這段腳本就會被執行,這東西后果挺嚴重啊,如果是在桌面外彈框,執行個挖礦腳本,這玩意不得了啊,厲害,長知識了。。。

    <dependency>
     <groupId>org.jsoup</groupId>
     <artifactId>jsoup</artifactId>
     <version>1.11.3</version>
    </dependency>

    看完上述內容,你們掌握springboot中怎么使用過濾器以及jsoup過濾XSS腳本怎么寫的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女