java防止XSS、SQL注入攻擊

1.XSS簡介

跨站腳本(cross site script)簡稱爲XSS,是一種經常出現在web應用中的計算機安全漏洞,也是web中最主流的攻擊方式。

XSS是指惡意攻擊者利用網站沒有對用戶提交數據進行轉義處理或者過濾不足的缺點,進而添加一些代碼,嵌入到web頁面中去,使別的用戶訪問都會執行相應的嵌入代碼。

  •  1.1.XSS攻擊的危害

     1、盜取用戶資料,比如:登錄帳號、網銀帳號等

     2、利用用戶身份,讀取、篡改、添加、刪除企業敏感數據等

     3、盜竊企業重要的具有商業價值的資料

     4、非法轉賬

     5、強制發送電子郵件

     6、網站掛馬

     7、控制受害者機器向其它網站發起攻擊

  • 1.2.防止XSS解決方案

XSS的根源主要是沒完全過濾客戶端提交的數據 ,所以重點是要過濾用戶提交的信息。

  •  將重要的cookie標記爲http only, 這樣的話js 中的document.cookie語句就不能獲取到cookie了.
  •  只允許用戶輸入我們期望的數據。 例如:age用戶年齡只允許用戶輸入數字,而數字之外的字符都過濾掉。
  •  對數據進行Html Encode 處理: 用戶將數據提交上來的時候進行HTML編碼,將相應的符號轉換爲實體名稱再進行下一步的處理。
  •  過濾或移除特殊的Html標籤, 例如: <script>, <iframe> , < for <, > for >, &quot for
  •  過濾js事件的標籤。例如 “οnclick=”, “onfocus” 等等。

 2.SQL注入簡介

        SQL注入是比較常見的網絡攻擊方式之一,主要是通過把SQL命令插入到Web表單遞交或輸入域名或頁面請求的查詢字符串,實現無帳號登錄,甚至篡改數據庫。

  • 2.1SQL注入的危害

       1.數據庫信息泄漏:數據庫中存放的用戶的隱私信息的泄露。

       2. 網頁篡改:通過操作數據庫對特定網頁進行篡改。

       3. 數據庫被惡意操作:數據庫服務器被攻擊

       4. 服務器被遠程控制,被安裝後門

       5. 刪除和修改數據庫信息

  • 2.2.防止SQL注入的方式

     通常情況下,SQL注入的位置包括:

    (1)表單提交,主要是POST請求,也包括GET請求;

    (2)URL參數提交,主要爲GET請求參數;

    (3)Cookie參數提交;

    (4)HTTP請求頭部的一些可修改的值,比如Referer、User_Agent等;

  • 2.3.防止SQL注入的解決方案

    (1)對用戶的輸入進行校驗,使用正則表達式過濾傳入的參數

   (2)使用參數化語句,不要拼接sql,也可以使用安全的存儲過程

   (3)不要使用管理員權限的數據庫連接,爲每個應用使用權限有限的數據庫連接

   (4)檢查數據存儲類型

   (5)重要的信息一定要加密

項目以SpringBoot項目爲例的代碼示例:

XssFilter:

  1. import javax.servlet.*;
  2. import javax.servlet.http.HttpServletRequest;
  3. import java.io.IOException;
  4. import java.util.List;
  5. @Compent
  6. public class XssFilter implements Filter {
  7. FilterConfig filterConfig = null;
  8. private List<String> urlExclusion = null;
  9. public void init(FilterConfig filterConfig) throws ServletException {
  10. this.filterConfig = filterConfig;
  11. }
  12. public void destroy() {
  13. this.filterConfig = null;
  14. }
  15. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  16. HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  17. String servletPath = httpServletRequest.getServletPath();
  18. if (urlExclusion != null && urlExclusion.contains(servletPath)) {
  19. chain.doFilter(request, response);
  20. } else {
  21. chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
  22. }
  23. }
  24. public List<String> getUrlExclusion() {
  25. return urlExclusion;
  26. }
  27. public void setUrlExclusion(List<String> urlExclusion) {
  28. this.urlExclusion = urlExclusion;
  29. }
  30. }

XssHttpServletRequestWrapper:

  1. import javax.servlet.http.HttpServletRequest;
  2. import javax.servlet.http.HttpServletRequestWrapper;
  3. public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
  4. public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
  5. super(servletRequest);
  6. }
  7. public String[] getParameterValues(String parameter) {
  8. String[] values = super.getParameterValues(parameter);
  9. if (values == null) {
  10. return null;
  11. }
  12. int count = values.length;
  13. String[] encodedValues = new String[count];
  14. for (int i = 0; i < count; i++) {
  15. encodedValues[i] = cleanXSS(values[i]);
  16. }
  17. return encodedValues;
  18. }
  19. public String getParameter(String parameter) {
  20. String value = super.getParameter(parameter);
  21. if (value == null) {
  22. return null;
  23. }
  24. return cleanXSS(value);
  25. }
  26. public String getHeader(String name) {
  27. String value = super.getHeader(name);
  28. if (value == null)
  29. return null;
  30. return cleanXSS(value);
  31. }
  32. private String cleanXSS(String value) {
  33. //You'll need to remove the spaces from the html entities below
  34. value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
  35. value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
  36. value = value.replaceAll("'", "& #39;");
  37. value = value.replaceAll("eval\\((.*)\\)", "");
  38. value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
  39. value = value.replaceAll("script", "");
  40. return value;
  41. }
  42. }

以上是其配置,在其攔截器或者過濾器對於某個請求進行Xss 和  Sql注入避免的操作:

GetRequest:

  1. /**
  2. * 獲取包裝防Xss Sql注入的 HttpServletRequest
  3. * @return request
  4. */
  5. public static HttpServletRequest getRequest() {
  6. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  7. return new WafRequestWrapper(request);
  8. }

WafRequestWrapper:

  1. public class WafRequestWrapper extends HttpServletRequestWrapper {
  2. private boolean filterXSS = true;
  3. private boolean filterSQL = true;
  4. public WafRequestWrapper(HttpServletRequest request, boolean filterXSS, boolean filterSQL) {
  5. super(request);
  6. this.filterXSS = filterXSS;
  7. this.filterSQL = filterSQL;
  8. }
  9. public WafRequestWrapper(HttpServletRequest request) {
  10. this(request, true, true);
  11. }
  12. /**
  13. * @Description 數組參數過濾
  14. * @param parameter
  15. * 過濾參數
  16. * @return
  17. */
  18. @Override
  19. public String[] getParameterValues(String parameter) {
  20. String[] values = super.getParameterValues(parameter);
  21. if ( values == null ) {
  22. return null;
  23. }
  24. int count = values.length;
  25. String[] encodedValues = new String[count];
  26. for ( int i = 0 ; i < count ; i++ ) {
  27. encodedValues[i] = filterParamString(values[i]);
  28. }
  29. return encodedValues;
  30. }
  31. @Override
  32. @SuppressWarnings({ "rawtypes", "unchecked" })
  33. public Map getParameterMap() {
  34. Map<String, String[]> primary = super.getParameterMap();
  35. Map<String, String[]> result = new HashMap<String, String[]>(primary.size());
  36. for ( Map.Entry<String, String[]> entry : primary.entrySet() ) {
  37. result.put(entry.getKey(), filterEntryString(entry.getValue()));
  38. }
  39. return result;
  40. }
  41. protected String[] filterEntryString(String[] rawValue) {
  42. for ( int i = 0 ; i < rawValue.length ; i++ ) {
  43. rawValue[i] = filterParamString(rawValue[i]);
  44. }
  45. return rawValue;
  46. }
  47. /**
  48. * @Description 參數過濾
  49. * @param parameter
  50. * 過濾參數
  51. * @return
  52. */
  53. @Override
  54. public String getParameter(String parameter) {
  55. return filterParamString(super.getParameter(parameter));
  56. }
  57. /**
  58. * @Description 請求頭過濾
  59. * @param name
  60. * 過濾內容
  61. * @return
  62. */
  63. @Override
  64. public String getHeader(String name) {
  65. return filterParamString(super.getHeader(name));
  66. }
  67. /**
  68. * @Description Cookie內容過濾
  69. * @return
  70. */
  71. @Override
  72. public Cookie[] getCookies() {
  73. Cookie[] existingCookies = super.getCookies();
  74. if (existingCookies != null) {
  75. for (int i = 0 ; i < existingCookies.length ; ++i) {
  76. Cookie cookie = existingCookies[i];
  77. cookie.setValue(filterParamString(cookie.getValue()));
  78. }
  79. }
  80. return existingCookies;
  81. }
  82. /**
  83. * @Description 過濾字符串內容
  84. * @param rawValue
  85. * 待處理內容
  86. * @return
  87. */
  88. protected String filterParamString(String rawValue) {
  89. if (null == rawValue) {
  90. return null;
  91. }
  92. String tmpStr = rawValue;
  93. if (this.filterXSS) {
  94. tmpStr = stripXSS(rawValue);
  95. }
  96. if (this.filterSQL) {
  97. tmpStr = stripSqlInjection(tmpStr);
  98. }
  99. return tmpStr;
  100. }
  101. /**
  102. * @Description 過濾XSS腳本內容
  103. * @param value
  104. * 待處理內容
  105. * @return
  106. */
  107. public static String stripXSS(String value) {
  108. String rlt = null;
  109. if (null != value) {
  110. // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
  111. // avoid encoded attacks.
  112. // value = ESAPI.encoder().canonicalize(value);
  113. // Avoid null characters
  114. rlt = value.replaceAll("", "");
  115. // Avoid anything between script tags
  116. Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
  117. rlt = scriptPattern.matcher(rlt).replaceAll("");
  118. // Avoid anything in a src='...' type of expression
  119. /*scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE
  120. | Pattern.MULTILINE | Pattern.DOTALL);
  121. rlt = scriptPattern.matcher(rlt).replaceAll("");
  122. scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE
  123. | Pattern.MULTILINE | Pattern.DOTALL);
  124. rlt = scriptPattern.matcher(rlt).replaceAll("");*/
  125. // Remove any lonesome </script> tag
  126. scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
  127. rlt = scriptPattern.matcher(rlt).replaceAll("");
  128. // Remove any lonesome <script ...> tag
  129. scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE
  130. | Pattern.MULTILINE | Pattern.DOTALL);
  131. rlt = scriptPattern.matcher(rlt).replaceAll("");
  132. // Avoid eval(...) expressions
  133. scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE
  134. | Pattern.MULTILINE | Pattern.DOTALL);
  135. rlt = scriptPattern.matcher(rlt).replaceAll("");
  136. // Avoid expression(...) expressions
  137. scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE
  138. | Pattern.MULTILINE | Pattern.DOTALL);
  139. rlt = scriptPattern.matcher(rlt).replaceAll("");
  140. // Avoid javascript:... expressions
  141. scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
  142. rlt = scriptPattern.matcher(rlt).replaceAll("");
  143. // Avoid vbscript:... expressions
  144. scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
  145. rlt = scriptPattern.matcher(rlt).replaceAll("");
  146. // Avoid expressions
  147. scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE
  148. | Pattern.MULTILINE | Pattern.DOTALL);
  149. rlt = scriptPattern.matcher(rlt).replaceAll("");
  150. }
  151. return rlt;
  152. }
  153. /**
  154. * @Description 過濾SQL注入內容
  155. * @param value
  156. * 待處理內容
  157. * @return
  158. */
  159. public static String stripSqlInjection(String value) {
  160. return (null == value) ? null : value.replaceAll("('.+--)|(--)|(%7C)", ""); //value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", "");
  161. }
  162. /**
  163. * @Description 過濾SQL/XSS注入內容
  164. * @param value
  165. * 待處理內容
  166. * @return
  167. */
  168. public static String stripSqlXSS(String value) {
  169. return stripXSS(stripSqlInjection(value));
  170. }
  171. }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章