XSS即惡意腳本攻擊漏洞,詳細的描述網上介紹的很詳細。我說一下自己在工作中對這種漏洞的修復方案,僅供參考。
第一階段:使用ESAPI
這是一個Apache開發的安全組件,主要用於解決SQL注入和惡意腳本注入。
使用ESAPI防止XSS攻擊時,首先應當配置過濾器(注意在過濾器中chain.doFilter(..)方法中的Request對象進行包裝,在包裝類中對請求參數進行篩選操作);其次將過濾器注冊到web.xml文件中;最后配置Request的包裝類,在其中對請求信息進行過濾。

1 import java.io.IOException; 2 import javax.servlet.Filter; 3 import javax.servlet.FilterChain; 4 import javax.servlet.FilterConfig; 5 import javax.servlet.ServletException; 6 import javax.servlet.ServletRequest; 7 import javax.servlet.ServletResponse; 8 import javax.servlet.http.HttpServletRequest; 9 10 /* 11 *配置XSS過濾器 12 */ 13 public class XSSFilter implements Filter { 14 @Override 15 public void init(FilterConfig filterConfig) throws ServletException { 16 } 17 @Override 18 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 19 throws IOException, ServletException { 20 chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response); 21 } 22 @Override 23 public void destroy() { 24 } 25 }

1 <!-- XSS攻擊防范 --> 2 <filter> 3 <filter-name>XSSFilter</filter-name> 4 <filter-class>過濾器全類名</filter-class> 5 </filter> 6 <filter-mapping> 7 <filter-name>XSSFilter</filter-name> 8 <url-pattern>/*</url-pattern> 9 <dispatcher>REQUEST</dispatcher> 10 <dispatcher>FORWARD</dispatcher> 11 </filter-mapping>

1 import java.net.URLDecoder; 2 import java.util.regex.Pattern; 3 import javax.servlet.http.HttpServletRequest; 4 import javax.servlet.http.HttpServletRequestWrapper; 5 import org.owasp.esapi.ESAPI; 6 7 /* 8 * 對傳入參數進行校驗 9 */ 10 public class XSSRequestWrapper extends HttpServletRequestWrapper { 11 public XSSRequestWrapper(HttpServletRequest servletRequest) { 12 super(servletRequest); 13 } 14 @Override 15 public String[] getParameterValues(String parameter) { 16 String[] values = super.getParameterValues(parameter); 17 if (values == null) { 18 return null; 19 } 20 int count = values.length; 21 String[] encodedValues = new String[count]; 22 for (int i = 0; i < count; i++) { 23 encodedValues[i] = stripXSS(values[i]); 24 } 25 return encodedValues; 26 } 27 @Override 28 public String getParameter(String parameter) { 29 String value = super.getParameter(parameter); 30 return stripXSS(value); 31 } 32 @Override 33 public String getHeader(String name) { 34 String value = super.getHeader(name); 35 return stripXSS(value); 36 } 37 38 private String stripXSS(String value) { 39 if (value != null) { 40 //解析URL編碼,防止前台的編碼后的參數進入ESAPI過濾后無法正常解碼 41 value = URLDecoder.decode(value); 42 // 使用ESAPI的防護功能避免XSS攻擊 43 value = ESAPI.encoder().canonicalize(value); 44 // 去除空字符 45 value = value.replaceAll("", ""); 46 // 過濾腳本標簽間(如:<script>..</script>)的內容 47 Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE); 48 value = scriptPattern.matcher(value).replaceAll(""); 49 //過濾由項目路徑(src)直接訪問項目資源的行為 50 scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 51 value = scriptPattern.matcher(value).replaceAll(""); 52 scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 53 value = scriptPattern.matcher(value).replaceAll(""); 54 // 過濾單個</script>標簽 55 scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE); 56 value = scriptPattern.matcher(value).replaceAll(""); 57 // 過濾單個<script ...> 標簽 58 scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 59 value = scriptPattern.matcher(value).replaceAll(""); 60 // 過濾 eval(...) 表達式 61 scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 62 value = scriptPattern.matcher(value).replaceAll(""); 63 // 過濾expression(...) 表達式 64 scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 65 value = scriptPattern.matcher(value).replaceAll(""); 66 // 過濾javascript:表達式攻擊 67 scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE); 68 value = scriptPattern.matcher(value).replaceAll(""); 69 // 過濾vbscript:表達式攻擊 70 scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE); 71 value = scriptPattern.matcher(value).replaceAll(""); 72 // 過濾onload=事件 73 scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); 74 value = scriptPattern.matcher(value).replaceAll(""); 75 } 76 return value; 77 } 78 }
注意:開啟ESAPI的防護功能時(value = ESAPI.encoder().canonicalize(value);),需要提前對要篩選的值進行URL解碼(value = URLDecoder.decode(value);),否則會出現中文亂碼。
第二階段(可選):使用CSF(Content Security Policy)安全策略
CSF是一種白名單防御策略,所有不在名單內的資源都不被信任,有效的防止了通過外部的標簽、腳本、JS文件等資源的入侵形式,詳情請看http://www.ruanyifeng.com/blog/2016/09/csp.html,我也是在這位大佬的網站上學習的CSF.
使用方式:
1.通過<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none'; style-src cdn.example.org third-party.org; child-src https:">標簽將CSP嵌入到頁面中。但是這種做法會對所有頁面添加一個過濾項,加長了頁面的訪問時間,降低了用戶體驗;我加到項目中的時候還出現了某些樣式文件加載不全的現象,沒有必要不建議這么做。
2.通過使用Nginx配置HTTP 頭信息的Content-Security-Policy的字段,但是一般的公司都不允許更改Nginx,一旦Nginx做了某種配置,整個項目都受影響,這種方式基本沒戲。