xss攻擊預防,網上有很多介紹,發現很多都是只能預防GET方式請求的xss攻擊,並不能預防POST方式的xss攻擊。主要是由於POST方式的參數只能用流的方式讀取,且只能讀取一次,經過多次嘗試,自己總結並經過多次嘗試之后,終於成功了,廢話不多說,上代碼。 |
參考主要網址: http://blog.csdn.net/Lan_Xuan/article/details/73826065 http://blog.csdn.net/happylee6688/article/details/40660797 http://www.cnblogs.com/digdeep/p/4695348.html |
maven依賴: <dependency> |
web.xml
1 <filter> 2 <filter-name>XssEscape</filter-name> 3 <filter-class>com.*.webshell.XSSFilter</filter-class> 4 </filter> 5 <filter-mapping> 6 <filter-name>XssEscape</filter-name> 7 <url-pattern>/*</url-pattern> 8 <dispatcher>REQUEST</dispatcher> 9 </filter-mapping>
XFFFilter.java
1 import java.io.IOException; 2 3 import javax.servlet.Filter; 4 import javax.servlet.FilterChain; 5 import javax.servlet.FilterConfig; 6 import javax.servlet.ServletException; 7 import javax.servlet.ServletRequest; 8 import javax.servlet.ServletResponse; 9 import javax.servlet.http.HttpServletRequest; 10 11 public class XSSFilter implements Filter { 12 13 FilterConfig filterConfig = null; 14 15 public void init(FilterConfig filterConfig) throws ServletException { 16 this.filterConfig = filterConfig; 17 } 18 19 public void destroy() { 20 this.filterConfig = null; 21 } 22 23 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 24 throws IOException, ServletException { 25 chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response); 26 } 27 }
XssHttpServletRequestWrapper.java
1 import java.io.BufferedReader; 2 import java.io.ByteArrayInputStream; 3 import java.io.IOException; 4 import java.io.InputStreamReader; 5 import java.io.UnsupportedEncodingException; 6 import java.nio.charset.Charset; 7 8 import javax.servlet.ReadListener; 9 import javax.servlet.ServletInputStream; 10 import javax.servlet.http.HttpServletRequest; 11 import javax.servlet.http.HttpServletRequestWrapper; 12 13 public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { 14 boolean isUpData = false;// 判斷是否是上傳 上傳忽略 15 16 public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { 17 super(servletRequest); 18 String contentType = servletRequest.getContentType(); 19 if (null != contentType) 20 isUpData = contentType.startsWith("multipart"); 21 } 22 23 @Override 24 public String[] getParameterValues(String parameter) { 25 String[] values = super.getParameterValues(parameter); 26 if (values == null) { 27 return null; 28 } 29 int count = values.length; 30 String[] encodedValues = new String[count]; 31 for (int i = 0; i < count; i++) { 32 encodedValues[i] = cleanXSS(values[i]); 33 } 34 return encodedValues; 35 } 36 37 @Override 38 public String getParameter(String parameter) { 39 String value = super.getParameter(parameter); 40 if (value == null) { 41 return null; 42 } 43 return cleanXSS(value); 44 } 45 46 /** 47 * 獲取request的屬性時,做xss過濾 48 */ 49 @Override 50 public Object getAttribute(String name) { 51 Object value = super.getAttribute(name); 52 if (null != value && value instanceof String) { 53 value = cleanXSS((String) value); 54 } 55 return value; 56 } 57 58 @Override 59 public String getHeader(String name) { 60 61 String value = super.getHeader(name); 62 if (value == null) 63 return null; 64 return cleanXSS(value); 65 } 66 67 private static String cleanXSS(String value) { 68 //幾種常見的web攻擊:http://jingyan.baidu.com/article/0202781178e19e1bcc9ce5c7.html 69 value = value.replaceAll("<", "<").replaceAll(">", ">"); 70 //%3C是URL對<字符的編碼 71 value = value.replaceAll("%3C", "<").replaceAll("%3E", ">"); 72 value = value.replaceAll("\\(", "(").replaceAll("\\)", ")"); 73 //%28是(轉義后的字符編碼 , %29是)轉義后的字符編碼 74 value = value.replaceAll("%28", "(").replaceAll("%29", ")"); 75 //'是單引號ASCII編碼后的表現形式 76 value = value.replaceAll("'", "'"); 77 //eval() 函數可計算某個字符串,並執行其中的的 JavaScript 代碼 78 value = value.replaceAll("eval\\((.*)\\)", ""); 79 //防止如javascript:alert(doucment.cookie)可以看到當前站點的cookie(如果有的話)的攻擊 80 value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); 81 // value = value.replaceAll("script", ""); 82 return value; 83 } 84 85 @Override 86 public ServletInputStream getInputStream() { 87 try { 88 if (isUpData) { 89 return super.getInputStream(); 90 } else { 91 92 final ByteArrayInputStream bais = new ByteArrayInputStream( 93 inputHandlers(super.getInputStream()).getBytes("utf-8")); 94 95 return new ServletInputStream() { 96 97 @Override 98 public int read() throws IOException { 99 return bais.read(); 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 } catch (UnsupportedEncodingException e) { 118 e.printStackTrace(); 119 } catch (IOException e) { 120 e.printStackTrace(); 121 } 122 return null; 123 124 } 125 126 public String inputHandlers(ServletInputStream servletInputStream) { 127 StringBuilder sb = new StringBuilder(); 128 BufferedReader reader = null; 129 try { 130 reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8"))); 131 String line = ""; 132 while ((line = reader.readLine()) != null) { 133 sb.append(line); 134 } 135 } catch (IOException e) { 136 e.printStackTrace(); 137 } finally { 138 if (servletInputStream != null) { 139 try { 140 servletInputStream.close(); 141 } catch (IOException e) { 142 e.printStackTrace(); 143 } 144 } 145 if (reader != null) { 146 try { 147 reader.close(); 148 } catch (IOException e) { 149 e.printStackTrace(); 150 } 151 } 152 } 153 return cleanXSS(sb.toString()); 154 } 155 }
如果XssHttpServletRequestWrapper.java類中沒有標紅的那個代碼會報如下錯誤,主要是因為過濾的參數中有中文:
1 org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Invalid UTF-8 start byte 0xb1 2 at [Source: com.*.XssHttpServletRequestWrapper$1@6230dd4f; line: 1, column: 128] 3 (through reference chain: com.*.entity.OrderTicket["address"]); 4 nested exception is com.fasterxml.jackson.databind.JsonMappingException: Invalid UTF-8 start byte 0xb1 5 at [Source: com.*.XssHttpServletRequestWrapper$1@6230dd4f; line: 1, column: 128] 6 (through reference chain: com.*.entity.*["address"])