什麼是XSS?css
百度百科的解釋: XSS又叫CSS (Cross Site Script) ,跨站腳本攻擊。它指的是惡意攻擊者往Web頁面裏插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web裏面的html代碼會被執行,從而達到惡意用戶的特殊目的。html
它與SQL注入攻擊相似,SQL注入攻擊中以SQL語句做爲用戶輸入,從而達到查詢/修改/刪除數據的目的,而在xss攻擊中,經過插入惡意腳本,實現對用戶遊覽器的控制,獲取用戶的一些信息。java
xss攻擊能夠分紅兩種類型:spring
1.非持久型攻擊
2.持久型攻擊數據庫
非持久型xss攻擊:顧名思義,非持久型xss攻擊是一次性的,僅對當次的頁面訪問產生影響。非持久型xss攻擊要求用戶訪問一個被攻擊者篡改後的連接,用戶訪問該連接時,被植入的攻擊腳本被用戶遊覽器執行,從而達到攻擊目的。apache
持久型xss攻擊:持久型xss,會把攻擊者的數據存儲在服務器端,攻擊行爲將伴隨着攻擊數據一直存在。 json
也能夠分紅三類:後端
反射型:通過後端,不通過數據庫數組
存儲型:通過後端,通過數據庫服務器
先加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是否是!