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 >, " 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:
- import javax.servlet.*;
- import javax.servlet.http.HttpServletRequest;
- import java.io.IOException;
- import java.util.List;
-
- @Compent
- public class XssFilter implements Filter {
-
- FilterConfig filterConfig = null;
-
- private List<String> urlExclusion = null;
-
- public void init(FilterConfig filterConfig) throws ServletException {
- this.filterConfig = filterConfig;
- }
-
- public void destroy() {
- this.filterConfig = null;
- }
-
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
- HttpServletRequest httpServletRequest = (HttpServletRequest) request;
- String servletPath = httpServletRequest.getServletPath();
-
- if (urlExclusion != null && urlExclusion.contains(servletPath)) {
- chain.doFilter(request, response);
- } else {
- chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
- }
- }
-
- public List<String> getUrlExclusion() {
- return urlExclusion;
- }
-
- public void setUrlExclusion(List<String> urlExclusion) {
- this.urlExclusion = urlExclusion;
- }
- }
XssHttpServletRequestWrapper:
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletRequestWrapper;
-
-
- public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
-
- public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
-
- super(servletRequest);
-
- }
-
- public String[] getParameterValues(String parameter) {
-
- String[] values = super.getParameterValues(parameter);
-
- if (values == null) {
-
- return null;
-
- }
-
- int count = values.length;
-
- String[] encodedValues = new String[count];
-
- for (int i = 0; i < count; i++) {
-
- encodedValues[i] = cleanXSS(values[i]);
-
- }
-
- return encodedValues;
-
- }
-
- public String getParameter(String parameter) {
-
- String value = super.getParameter(parameter);
-
- if (value == null) {
-
- return null;
-
- }
-
- return cleanXSS(value);
-
- }
-
- public String getHeader(String name) {
-
- String value = super.getHeader(name);
-
- if (value == null)
-
- return null;
-
- return cleanXSS(value);
-
- }
-
- private String cleanXSS(String value) {
-
- //You'll need to remove the spaces from the html entities below
-
- value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
-
- value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
-
- value = value.replaceAll("'", "& #39;");
-
- value = value.replaceAll("eval\\((.*)\\)", "");
-
- value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
-
- value = value.replaceAll("script", "");
-
- return value;
-
- }
-
-
- }
以上是其配置,在其攔截器或者過濾器對於某個請求進行Xss 和 Sql注入避免的操作:
GetRequest:
-
- /**
- * 獲取包裝防Xss Sql注入的 HttpServletRequest
- * @return request
- */
- public static HttpServletRequest getRequest() {
- HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
- return new WafRequestWrapper(request);
- }
-
-
WafRequestWrapper:
- public class WafRequestWrapper extends HttpServletRequestWrapper {
-
- private boolean filterXSS = true;
-
- private boolean filterSQL = true;
-
-
- public WafRequestWrapper(HttpServletRequest request, boolean filterXSS, boolean filterSQL) {
- super(request);
- this.filterXSS = filterXSS;
- this.filterSQL = filterSQL;
- }
-
-
- public WafRequestWrapper(HttpServletRequest request) {
- this(request, true, true);
- }
-
-
- /**
- * @Description 數組參數過濾
- * @param parameter
- * 過濾參數
- * @return
- */
- @Override
- public String[] getParameterValues(String parameter) {
- String[] values = super.getParameterValues(parameter);
- if ( values == null ) {
- return null;
- }
-
- int count = values.length;
- String[] encodedValues = new String[count];
- for ( int i = 0 ; i < count ; i++ ) {
- encodedValues[i] = filterParamString(values[i]);
- }
-
- return encodedValues;
- }
-
- @Override
- @SuppressWarnings({ "rawtypes", "unchecked" })
- public Map getParameterMap() {
- Map<String, String[]> primary = super.getParameterMap();
- Map<String, String[]> result = new HashMap<String, String[]>(primary.size());
- for ( Map.Entry<String, String[]> entry : primary.entrySet() ) {
- result.put(entry.getKey(), filterEntryString(entry.getValue()));
- }
- return result;
-
- }
-
- protected String[] filterEntryString(String[] rawValue) {
- for ( int i = 0 ; i < rawValue.length ; i++ ) {
- rawValue[i] = filterParamString(rawValue[i]);
- }
- return rawValue;
- }
-
- /**
- * @Description 參數過濾
- * @param parameter
- * 過濾參數
- * @return
- */
- @Override
- public String getParameter(String parameter) {
- return filterParamString(super.getParameter(parameter));
- }
-
-
- /**
- * @Description 請求頭過濾
- * @param name
- * 過濾內容
- * @return
- */
- @Override
- public String getHeader(String name) {
- return filterParamString(super.getHeader(name));
- }
-
-
- /**
- * @Description Cookie內容過濾
- * @return
- */
- @Override
- public Cookie[] getCookies() {
- Cookie[] existingCookies = super.getCookies();
- if (existingCookies != null) {
- for (int i = 0 ; i < existingCookies.length ; ++i) {
- Cookie cookie = existingCookies[i];
- cookie.setValue(filterParamString(cookie.getValue()));
- }
- }
- return existingCookies;
- }
-
- /**
- * @Description 過濾字符串內容
- * @param rawValue
- * 待處理內容
- * @return
- */
- protected String filterParamString(String rawValue) {
- if (null == rawValue) {
- return null;
- }
- String tmpStr = rawValue;
- if (this.filterXSS) {
- tmpStr = stripXSS(rawValue);
- }
- if (this.filterSQL) {
- tmpStr = stripSqlInjection(tmpStr);
- }
- return tmpStr;
- }
-
- /**
- * @Description 過濾XSS腳本內容
- * @param value
- * 待處理內容
- * @return
- */
- public static String stripXSS(String value) {
- String rlt = null;
-
- if (null != value) {
- // NOTE: It's highly recommended to use the ESAPI library and uncomment the following line to
- // avoid encoded attacks.
- // value = ESAPI.encoder().canonicalize(value);
-
- // Avoid null characters
- rlt = value.replaceAll("", "");
-
- // Avoid anything between script tags
- Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
- rlt = scriptPattern.matcher(rlt).replaceAll("");
-
- // Avoid anything in a src='...' type of expression
- /*scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE
- | Pattern.MULTILINE | Pattern.DOTALL);
- rlt = scriptPattern.matcher(rlt).replaceAll("");
- scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE
- | Pattern.MULTILINE | Pattern.DOTALL);
- rlt = scriptPattern.matcher(rlt).replaceAll("");*/
-
- // Remove any lonesome </script> tag
- scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
- rlt = scriptPattern.matcher(rlt).replaceAll("");
-
- // Remove any lonesome <script ...> tag
- scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE
- | Pattern.MULTILINE | Pattern.DOTALL);
- rlt = scriptPattern.matcher(rlt).replaceAll("");
-
- // Avoid eval(...) expressions
- scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE
- | Pattern.MULTILINE | Pattern.DOTALL);
- rlt = scriptPattern.matcher(rlt).replaceAll("");
-
- // Avoid expression(...) expressions
- scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE
- | Pattern.MULTILINE | Pattern.DOTALL);
- rlt = scriptPattern.matcher(rlt).replaceAll("");
-
- // Avoid javascript:... expressions
- scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
- rlt = scriptPattern.matcher(rlt).replaceAll("");
-
- // Avoid vbscript:... expressions
- scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
- rlt = scriptPattern.matcher(rlt).replaceAll("");
-
- // Avoid expressions
- scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE
- | Pattern.MULTILINE | Pattern.DOTALL);
- rlt = scriptPattern.matcher(rlt).replaceAll("");
- }
-
- return rlt;
- }
-
- /**
- * @Description 過濾SQL注入內容
- * @param value
- * 待處理內容
- * @return
- */
- public static String stripSqlInjection(String value) {
- return (null == value) ? null : value.replaceAll("('.+--)|(--)|(%7C)", ""); //value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", "");
- }
-
- /**
- * @Description 過濾SQL/XSS注入內容
- * @param value
- * 待處理內容
- * @return
- */
- public static String stripSqlXSS(String value) {
- return stripXSS(stripSqlInjection(value));
- }
-
- }