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就可以 ,切記不要用拼接字符串的方法就可以了