JavaWeb開發防止SQL、XSS注入

SQL注入簡介

SQL注入是比較常見的網絡攻擊方式之一,它不是利用操作系統的BUG來實現攻擊,而是針對程序員編程時的疏忽,通過SQL語句,實現無帳號登錄,甚至篡改數據庫。

SQL注入攻擊實例

比如在一個登錄界面,要求輸入用戶名和密碼:

可以這樣輸入實現免帳號登錄:

用戶名: ‘or 1 = 1 –

密 碼:

點登陸,如若沒有做特殊處理,那麼這個非法用戶就很得意的登陸進去了.(當然現在的有些語言的數據庫API已經處理了這些問題)

這是爲什麼呢? 下面我們分析一下:

從理論上說,後臺認證程序中會有如下的SQL語句:

String sql = "select * from user_table where username=

' "+userName+" ' and password=' "+password+" '";

當輸入了上面的用戶名和密碼,上面的SQL語句變成:

SELECT * FROM user_table WHERE username=

'’or 1 = 1 -- and password='’

分析SQL語句:

條件後面username=”or 1=1 用戶名等於 ” 或1=1 那麼這個條件一定會成功;

然後後面加兩個-,這意味着註釋,它將後面的語句註釋,讓他們不起作用,這樣語句永遠都能正確執行,用戶輕易騙過系統,獲取合法身份。

這還是比較溫柔的,如果是執行

SELECT * FROM user_table WHERE

username='' ;DROP DATABASE (DB Name) --' and password=''

….其後果可想而知…

應對方法

1、配置web.xml


 <!--過濾XSS注入 -->
  <filter>
    <filter-name>XssEscape</filter-name>
    <filter-class>com.cm.contract.filter.XSSFilter.XssFilter</filter-class>
  </filter>
  
  <filter-mapping>
    <filter-name>XssEscape</filter-name>
  <url-pattern>/*</url-pattern>
  <dispatcher>REQUEST</dispatcher>
  </filter-mapping>
  <!--過濾SQL注入 -->
  <filter>  
     <filter-name>SqlFilter</filter-name>  
     <filter-class>com.cm.contract.filter.SQLFilter.SqlFilter</filter-class>  
   </filter>  
   <filter-mapping>  
       <filter-name>SqlFilter</filter-name>  
       <url-pattern>/*</url-pattern>  
   </filter-mapping>   


2、SqlFilter.java

package com.cm.contract.filter.SQLFilter;
import java.io.IOException;  
import java.util.Enumeration;  
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
/** 
* 過濾sql關鍵字的Filter 
* @author FengArWei
 
*/  
public class SqlFilter implements Filter {  
  
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {  
  
        HttpServletRequest req = (HttpServletRequest) request;  
        HttpServletResponse res = (HttpServletResponse) response;  
        //獲得所有請求參數名  
        @SuppressWarnings("rawtypes")
		Enumeration params = req.getParameterNames();  
  
        String sql = "";  
        while (params.hasMoreElements()) {  
            //得到參數名  
            String name = params.nextElement().toString();  
            //System.out.println("name===========================" + name + "--");  
            //得到參數對應值  
            String[] value = req.getParameterValues(name);  
            for (int i = 0; i < value.length; i++) {  
                sql = sql + value[i];  
            }  
        }  
        //System.out.println("============================SQL"+sql);  
        //有sql關鍵字,跳轉到error.html  
        if (sqlValidate(sql)) {  
            res.sendRedirect("error.html");  
            //String ip = req.getRemoteAddr();  
        } else {  
            chain.doFilter(req, res);  
        }  
    }  
  
    //效驗  
    protected static boolean sqlValidate(String str) {  
        str = str.toLowerCase();//統一轉爲小寫  
        String badStr = "'|and|exec|execute|insert|create|drop|table|from|grant|use|group_concat|column_name|" +  
                "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +  
                "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";//過濾掉的sql關鍵字,可以手動添加  
        String[] badStrs = badStr.split("|");  
        for (int i = 0; i < badStrs.length; i++) {  
            if (str.indexOf(badStrs[i]) !=-1) {  
                return true;  
            }  
        }  
        return false;  
    }  
  
    public void init(FilterConfig filterConfig) throws ServletException {  
        //throw new UnsupportedOperationException("Not supported yet.");  
    }  
  
    public void destroy() {  
        //throw new UnsupportedOperationException("Not supported yet.");  
    }  
}
3、XssFilter.java

package com.cm.contract.filter.XSSFilter;

import java.io.IOException;  

import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
import javax.servlet.http.HttpServletRequest;  
  
public class XssFilter implements Filter {  
      
    @Override  
    public void init(FilterConfig filterConfig) throws ServletException {  
    }  
  
    @Override  
    public void doFilter(ServletRequest request, ServletResponse response,  
            FilterChain chain) throws IOException, ServletException {  
        chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);  
    }  
  
    @Override  
    public void destroy() {  
    }  
} 
4、XssHttpServletRequestWrapper.java

package com.cm.contract.filter.XSSFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.lang3.StringEscapeUtils;

public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {  
  
    public XssHttpServletRequestWrapper(HttpServletRequest request) {  
        super(request);  
    }  
  
    @Override  
    public String getHeader(String name) {  
        return StringEscapeUtils.escapeHtml4(super.getHeader(name));  
    }  
  
    @Override  
    public String getQueryString() {  
        return StringEscapeUtils.escapeHtml4(super.getQueryString());  
    }  
  
    @Override  
    public String getParameter(String name) {  
        return StringEscapeUtils.escapeHtml4(super.getParameter(name));  
    }  
  
    @Override  
    public String[] getParameterValues(String name) {  
        String[] values = super.getParameterValues(name);  
        if(values != null) {  
            int length = values.length;  
            String[] escapseValues = new String[length];  
            for(int i = 0; i < length; i++){  
                escapseValues[i] = StringEscapeUtils.escapeHtml4(values[i]);  
            }  
            return escapseValues;  
        }  
        return super.getParameterValues(name);  
    }  
      
} 

總的說來,防範一般的SQL注入只要在代碼規範上下點功夫就可以了。

凡涉及到執行的SQL中有變量時,用JDBC(或者其他數據持久層)提供的如:PreparedStatement就可以 ,切記不要用拼接字符串的方法就可以了





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章