SQL注入概念和解決

一、SQL注入概念

  SQL注入是指一種代碼注入技術,它通過Web頁面請求或提交表單的形式,提交惡意的SQL,以此達到攻擊數據庫驅動的目的。


二、SQL注入原理

  SQL注入可以使攻擊者繞過認證機制,通過執行惡意的SQL,獲取數據庫數據或權限,進一步理由計算機漏洞達到獲取計算機系統權限的目的。SQL是結構化查詢語言的簡稱,是一種數據庫查詢和程序設計語言,用於存取數據以及查詢、更新和管理關係數據庫系統。大多數應用服務器,其後臺都會使用到數據庫,因爲SQL語法允許數據庫命令和用戶數據混雜在一起的,所以用戶不僅可以通過Web輸入數據,也可輸入任意的SQL命令來操作數據庫。

SQL注入式攻擊的主要形式可以分爲兩種:

(1) 一種是直接注入攻擊法。其將惡意SQL與原始SQL命令串聯拼接在一起執行。如下面的例子:

原始SQL命令:


strSQL = "SELECT * FROM users WHERE name = '" + userName + "' and pw = '"+ passWord +"';
userName = "1' OR '1'='1";
passWord = "1' OR '1'='1";

注入後SQL:

SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1

相當於執行了:

SELECT * FROM users WHERE name 

(2) 一種是間接注入攻擊法。其將原始的SQL當做是一個數據操作的指令,而將惡意SQL通過分號的形式與原始SQL分割開,當做兩條命令來執行。一般在追加的前面會使用;來分割,後面使用--來註釋尾部SQL,執行時就會僅執行原始SQL和惡意SQL。

不僅可以通過Web輸入數據,也可輸入任意的SQL命令來操作數據庫。如下面例子:

同樣是上面的語句,我們插入數據爲:

userName = "'; DROP TABLE users--";
passWord = "'; DROP TABLE users--";
注入後SQL:

SELECT * FROM users WHERE name = ''; DROP TABLE users-- and pw = ''; DROP TABLE users--

相當於執行了:

SELECT * FROM users WHERE name = ''; 
DROP TABLE users;

至此就達到了刪庫跑路的目的。


三、SQL注入的一般過程

(1) 發現SQL注入位置

可以通過一些語句去試探動態頁面的入參是否存在SQL注入的可能。

(2) 判斷後臺數據庫類型

通過各個不同數據庫獨有的系統命令來判斷。

(3) 確定XP_CMDSHELL可執行情況

需要系統本身存在SQL與系統命令之間的通道,以此通過數據庫操作計算機。

(4) 發現WEB虛擬目錄

(5) 上傳ASP木馬

(6) 得到管理員權限


、防禦SQL注入攻擊

(1) 採用預編譯語句集,將SQL原句編譯後執行,這樣參數不能改變原有原句的命令。Java實例如下:

採用JDBC的可以這樣寫:

String sql= "select * from users where username=? and password=?";    
PreparedStatement preState = conn.prepareStatement(sql);    
preState.setString(1, userName);    
preState.setString(2, password);    
ResultSet rs = preState.executeQuery();

對於IN查詢,因爲IN查詢,因爲預編譯要確定參數的個數,所以可以採用如下寫法:

PreparedStatement statement = connection.prepareStatement("Select * from test where field in (?)");
Array array = statement.getConnection().createArrayOf("VARCHAR", new Object[]{"A1", "B2","C3"});
statement.setArray(1, array);
ResultSet rs = statement.executeQuery();

或者判斷入參的格式,構造IN(?,?,?)形式的入參。

採用Mybatis的可以這樣寫,XML文件:

<select id="getBlogById" resultType="Blog" parameterType=”int”>
         SELECT id,title,author,content
         FROM blog
         WHERE id=#{id}
</select>

Java文件:

filter.put("title", id);
Blog blog = loanMerchantMemDao.getBlogById(filter);  

採用Mybatis使用IN查詢的可以這樣寫,XML文件:

<select id="findByTitle" resultMap="Blog" parameterType="java.util.Map">  
    SELECT  
    <include refid="Column"/>  
    FROM blog
    WHERE title IN  
    <foreach collection="title" index="index" item="item" open="(" separator="," close=")">  
        #{item}  
    </foreach>  
</select>  

Java文件:

List<String> list = new ArrayList<String>();  
filter.put("title", list);
Blog blog = loanMerchantMemDao.findByTitle(filter);  

(2) 過濾敏感詞彙和超出長度限制的輸入,可以通過正則表達式或者方法判斷提交的請求或參數中是否包含敏感詞彙,例如; ' delete --等,然後過濾敏感詞彙,或者禁止本次請求發生。

(3) 區分普通用戶與系統管理員用戶。服務器上應用訪問數據庫都應使用普通用戶權限,防止其執行Drop Table,讀取系統表結構、創建表等語句,這樣在最大程度上可以減少注入攻擊帶來的危害。


參考:

(1) 談談六個防止SQL注入式攻擊的建議





發佈了25 篇原創文章 · 獲贊 32 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章