手寫SpringBoot項目XSS攻擊過濾器實現

1、先來個簡介

什麼是XSS?css

百度百科的解釋: XSS又叫CSS  (Cross Site Script) ,跨站腳本攻擊。它指的是惡意攻擊者往Web頁面裏插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web裏面的html代碼會被執行,從而達到惡意用戶的特殊目的。html

它與SQL注入攻擊相似,SQL注入攻擊中以SQL語句做爲用戶輸入,從而達到查詢/修改/刪除數據的目的,而在xss攻擊中,經過插入惡意腳本,實現對用戶遊覽器的控制,獲取用戶的一些信息。java

2、XSS分類

xss攻擊能夠分紅兩種類型:spring

1.非持久型攻擊
2.持久型攻擊數據庫

非持久型xss攻擊:顧名思義,非持久型xss攻擊是一次性的,僅對當次的頁面訪問產生影響。非持久型xss攻擊要求用戶訪問一個被攻擊者篡改後的連接,用戶訪問該連接時,被植入的攻擊腳本被用戶遊覽器執行,從而達到攻擊目的。apache

持久型xss攻擊:持久型xss,會把攻擊者的數據存儲在服務器端,攻擊行爲將伴隨着攻擊數據一直存在。 json

也能夠分紅三類:後端

反射型:通過後端,不通過數據庫數組

存儲型:通過後端,通過數據庫服務器

3、廢話很少說直接上代碼

先加pom文件加上依賴

1    <dependency>
2             <groupId>org.apache.commons</groupId>
3             <artifactId>commons-text</artifactId>
4             <version>1.4</version>
5    </dependency>

1.首先是要寫個過濾器的包裝類,這也是實現XSS攻擊過濾的核心代碼。

  1 package com.hrt.zxxc.fxspg.xss;
  2 
  3 import com.alibaba.fastjson.JSON;
  4 import org.apache.commons.lang3.StringUtils;
  5 import org.apache.commons.text.StringEscapeUtils;
  6 
  7 import javax.servlet.ReadListener;
  8 import javax.servlet.ServletInputStream;
  9 import javax.servlet.http.HttpServletRequest;
 10 import javax.servlet.http.HttpServletRequestWrapper;
 11 import java.io.*;
 12 import java.nio.charset.Charset;
 13 import java.util.HashMap;
 14 import java.util.Map;
 15 
 16 /**
 17  * @program: fxspg
 18  * @description: XSS過濾具體核心代碼
 19  * @author: liumingyu
 20  * @date: 2020-01-10 14:28
 21  **/
 22 public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {
 23 
 24     /**
 25      * @return
 26      * @Author liumingyu
 27      * @Description //TODO 構造函數,傳入參數,執行超類
 28      * @Date 2020/1/10 2:29 下午
 29      * @Param [request]
 30      **/
 31     public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) {
 32         super(request);
 33     }
 34 
 35     /**
 36      * @return java.lang.String
 37      * @Author liumingyu
 38      * @Description //TODO 重寫getParameter方法 ,getParameter方法是直接經過request得到querystring類型的入參調用的方法
 39      * @Date 2020/1/10 2:31 下午
 40      * @Param [name]
 41      **/
 42     @Override
 43     public String getParameter(String name) {
 44         String value = super.getParameter(name);
 45         if (!StringUtils.isEmpty(value)) {
 46             //調用Apache的工具類:StringEscapeUtils.escapeHtml4
 47             value = StringEscapeUtils.escapeHtml4(value);
 48         }
 49         return value;
 50     }
 51 
 52     /**
 53      * @return java.lang.String[]
 54      * @Author liumingyu
 55      * @Description //TODO 重寫getParameterValues
 56      * @Date 2020/1/10 2:32 下午
 57      * @Param [name]
 58      **/
 59     @Override
 60     public String[] getParameterValues(String name) {
 61         String[] parameterValues = super.getParameterValues(name);
 62         if (parameterValues == null) {
 63             return null;
 64         }
 65         for (int i = 0; i < parameterValues.length; i++) {
 66             String value = parameterValues[i];
 67             //調用Apache的工具類:StringEscapeUtils.escapeHtml4
 68             parameterValues[i] = StringEscapeUtils.escapeHtml4(value);
 69         }
 70         return parameterValues;
 71     }
 72 
 73     @Override
 74     public String getHeader(String name) {
 75         return StringEscapeUtils.escapeHtml4(super.getHeader(name));
 76     }
 77 
 78     @Override
 79     public String getQueryString() {
 80         return StringEscapeUtils.escapeHtml4(super.getQueryString());
 81     }
 82 
 83     /**
 84      * @return javax.servlet.ServletInputStream
 85      * @Author liumingyu
 86      * @Description //TODO 過濾JSON數據中的XSS攻擊
 87      * @Date 2020/1/10 4:58 下午
 88      * @Param []
 89      **/
 90     @Override
 91     public ServletInputStream getInputStream() throws IOException {
 92         //調用方法將流數據return爲String
 93         String str = getRequestBody(super.getInputStream());
 94         //若是str爲"",則返回0
 95         if ("".equals(str)) {
 96             return new ServletInputStream() {
 97                 @Override
 98                 public int read() throws IOException {
 99                     return 0;
100                 }
101 
102                 @Override
103                 public boolean isFinished() {
104                     return false;
105                 }
106 
107                 @Override
108                 public boolean isReady() {
109                     return false;
110                 }
111 
112                 @Override
113                 public void setReadListener(ReadListener readListener) {
114 
115                 }
116             };
117         }
118         //將數據存放至map
119         Map<String, Object> map = JSON.parseObject(str, Map.class);
120         //聲明個存放過濾後數據的hashMap
121         Map<String, Object> resultMap = new HashMap<>(map.size());
122         //開始遍歷數據
123         for (String key : map.keySet()) {
124             Object val = map.get(key);
125             //若是key=富文本字段名,就不去過濾
126             if ("content".equals(key)) {
127                 //不過濾
128                 resultMap.put(key, val);
129             } else {
130                 //不爲富文本字段纔會過濾
131                 if (map.get(key) instanceof String) {
132                     //經過escapeHtml4去過濾
133                     resultMap.put(key, StringEscapeUtils.escapeHtml4(val.toString()));
134                 } else {
135                     //不過濾
136                     resultMap.put(key, val);
137                 }
138             }
139         }
140         str = JSON.toJSONString(resultMap);
141         final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(str.getBytes());
142         return new ServletInputStream() {
143             @Override
144             public int read() throws IOException {
145                 return byteArrayInputStream.read();
146             }
147 
148             @Override
149             public boolean isFinished() {
150                 return false;
151             }
152 
153             @Override
154             public boolean isReady() {
155                 return false;
156             }
157 
158             @Override
159             public void setReadListener(ReadListener readListener) {
160 
161             }
162 
163         };
164     }
165 
166     /**
167      * @return java.lang.String
168      * @Author liumingyu
169      * @Description //TODO 獲取JSON數據
170      * @Date 2020/1/10 4:58 下午
171      * @Param [stream]
172      **/
173     private String getRequestBody(InputStream stream) {
174         String line = "";
175         StringBuilder body = new StringBuilder();
176         int counter = 0;
177         // 讀取POST提交的數據內容
178         BufferedReader reader = new BufferedReader(new InputStreamReader(stream, Charset.forName("UTF-8")));
179         try {
180             while ((line = reader.readLine()) != null) {
181                 //拼接讀取到的數據
182                 body.append(line);
183                 counter++;
184             }
185         } catch (IOException e) {
186             e.printStackTrace();
187         }
188         if (body == null) {
189             return "";
190         }
191         //最後返回數據
192         return body.toString();
193     }
194 
195 }

2.看到這裏你就已經完成了一半了加油!接下來的事情很簡單寫個過濾器就over 。

 1 package com.hrt.zxxc.fxspg.xss;
 2 
 3 import com.fasterxml.jackson.databind.ObjectMapper;
 4 import com.fasterxml.jackson.databind.module.SimpleModule;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Primary;
 7 import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
 8 import org.springframework.stereotype.Component;
 9 
10 import javax.servlet.*;
11 import javax.servlet.annotation.WebFilter;
12 import javax.servlet.http.HttpServletRequest;
13 import java.io.IOException;
14 
15 /**
16  * @program: fxspg
17  * @description: XSS過濾器
18  * @author: liumingyu
19  * @date: 2020-01-10 14:36
20  **/
21 
22 @WebFilter
23 @Component
24 public class XssFilter implements Filter {
25 
26     /**
27      * @return void
28      * @Author liumingyu
29      * @Description //TODO 重寫init
30      * @Date 2020/1/10 2:38 下午
31      * @Param [filterConfig]
32      **/
33     @Override
34     public void init(FilterConfig filterConfig) throws ServletException {
35 
36     }
37 
38     /**
39      * @return void
40      * @Author liumingyu
41      * @Description //TODO 重寫doFilter,將請求進行xss過濾
42      * @Date 2020/1/10 2:41 下午
43      * @Param [servletRequest, servletResponse, filterChain]
44      **/
45     @Override
46     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
47                          FilterChain filterChain) throws IOException, ServletException {
48         //獲取請求數據
49         HttpServletRequest req = (HttpServletRequest) servletRequest;
50         //獲取請求的url路徑
51         String path = ((HttpServletRequest) servletRequest).getServletPath();
52         //聲明要被忽略請求的數組
53         String[] exclusionsUrls = {".js", ".gif", ".jpg", ".png", ".css", ".ico"};
54         //遍歷忽略的請求數組,若該接口url爲忽略的就調用本來的過濾器,不走xss過濾
55         for (String str : exclusionsUrls) {
56             if (path.contains(str)) {
57                 filterChain.doFilter(servletRequest, servletResponse);
58                 return;
59             }
60         }
61         //將請求放入XSS請求包裝器中,返回過濾後的值
62         XssAndSqlHttpServletRequestWrapper xssRequestWrapper = new XssAndSqlHttpServletRequestWrapper(req);
63         filterChain.doFilter(xssRequestWrapper, servletResponse);
64     }
65 
66     @Override
67     public void destroy() {
68 
69     }
70 
71 }

注:上面的註釋我都寫得比較全了,不過多解釋,so easy是否是!

相關文章
相關標籤/搜索