SQL注入及防止注入措施

1、Sql注入是怎麼產生的?

  • WEB開發人員無法保證所有的輸入都已經過濾
  • 攻擊者利用發送給SQL服務器的輸入數據構造可執行的SQL代碼
  • 數據庫未做相應的安全配置

2、如何尋找Sql注入?

  • 識別web應用中的所有輸入點
  • 瞭解哪些類型的請求會出發異常
  • 檢測服務器響應中的異常

3、如何進行SQL注入攻擊?

  • 數字注入
    比如:用or 前一個條件不匹配後一個條件完全匹配。比如id = -1 or 1 = 1
  • 字符串注入
    比如:用 閉合查詢,然後後面添加#,用來將後面的語句註釋掉

4、如何預防SQL注入?

  • 嚴格檢查輸入變量的類型和格式
  • 過濾和轉義特殊字符
  • 利用mysql的預編譯機制

5、預編譯的相關知識

  sql注入只對sql語句的準備(編譯)過程有破壞作用,而PreparedStatement已經準備(編譯)好了,執行階段只是把輸入串作爲數據處理,而不再對sql語句進行解析、準備(編譯),因此也就避免了sql注入問題。

  • 什麼是預編譯語句
    預編譯語句PreparedStatement 是java.sql中的一個接口,它是Statement的子接口。通過Statement對象執行SQL語句時,需要將SQL語句發送給DBMS,由DBMS首先進行編譯後再執行。預編譯語句和Statement不同,在創建PreparedStatement 對象時就指定了SQL語句,該語句立即發送給DBMS進行編譯。當該編譯語句被執行時,DBMS直接運行編譯後的SQL語句,而不需要像其他SQL語句那樣首先將其編譯。
  • 什麼時候使用預編譯語句
    一般是在需要反覆使用一個SQL語句時才使用預編譯語句,預編譯語句常常放在一個fo r或者while循環裏面使用,通過反覆設置參數從而多次使用該SQL語句。爲了防止SQL注入漏洞,在某些數據操作中也使用預編譯語句。
  • 爲什麼使用預編譯語句
    預編譯機制除了在開篇提到的可以防止SQL注入外,還有一下兩方面的優點:
    a、提高效率:數據庫處理一個SQL語句,需要完成解析SQL語句、檢查語法和語義以及生成代碼,一般說來,處理時間要比執行語句所需要的時間長。預編譯語句在創建的時候已經是將指定的SQL語句發送給了DBMS,完成了解析、檢查、編譯等工作。因此,當一個SQL語句需要執行多次時,使用預編譯語句可以減少處理時間,提高執行效率。
    b、提高代碼的可讀性和可維護性:將參數與SQL語句分離出來,這樣就可以方便對程序的更改和擴展,同樣,也可以減少不必要的錯誤。

6、防止SQL注入以及預編譯機制在mybatis中的應用

‘#’ 與 ‘$’區別

 動態 SQL是 mybatis 的強大特性之一,也是它優於其他 ORM 框架的一個重要原因。mybatis 在對 sql 語句進行預編譯之前,會對 sql 進行動態解析,解析爲一個 BoundSql 對象,也是在此處對動態 SQL 進行處理的。
在動態 SQL 解析階段,#{ }${ } 會有不同的表現:
#{} 解析爲一個 JDBC 預編譯語句(prepared statement)的參數標記符。
 例如,sqlMap 中如下的 sql 語句

select * from user where name = #{name};

 解析爲:

select * from user where name = ?;

 一個 #{ } 被解析爲一個參數佔位符 ?
 而,${ } 僅僅爲一個純碎的 string 替換,在動態 SQL 解析階段將會進行變量替換
 例如,sqlMap 中如下的 sql

select * from user where name = ${name};

 當我們傳遞的參數爲 “ruhua” 時,上述 sql 的解析爲:

select * from user where name = "ruhua";

 預編譯之前的 SQL 語句已經不包含變量 name 了。
 綜上所得, ${ } 的變量的替換階段是在動態 SQL 解析階段,而 #{ }的變量的替換是在 DBMS 中。

7、mybatis中‘#’ 與 ‘$’的用法

能使用 #{ } 的地方就用 #{ }

首先這是爲了性能考慮的,相同的預編譯 sql 可以重複利用。
其次, ${ } 在預編譯之前已經被變量替換了,這會存在 sql 注入問題 。例如,如下的 sql,

select * from ${tableName} where name = #{name} 

假如,我們的參數 tableName 爲 user; delete user; – ,那麼 SQL 動態解析階段之後,預編譯之前的 sql 將變爲

select * from user; delete user; -- where name = ?;

之後的語句將作爲註釋,不起作用,因此本來的一條查詢語句偷偷的包含了一個刪除表數據的 SQL!
2、表名作爲變量時,必須使用 ${ }
這是因爲,表名是字符串,使用 sql 佔位符替換字符串時會帶上單引號 ” ,這會導致 sql 語法錯誤,例如:

select * from #{tableName} where name = #{name};

預編譯之後的sql 變爲:

select * from ? where name = ?;

假設我們傳入的參數爲 tableName = “user” , name = “ruhua”,那麼在佔位符進行變量替換後,sql 語句變爲

select * from 'user' where name='ruhua';

上述 sql 語句是存在語法錯誤的,表名不能加單引號 ” (注意,反引號 “是可以的)。

8、mybatis sql 動態解析

mybatis 在調用 connection 進行 sql 預編譯之前,會對sql語句進行動態解析,動態解析主要包含如下的功能:
* 佔位符的處理
* 動態sql的處理
* 參數類型校驗

9、以上內容由本人學習慕課網課程:web安全之SQL注入及其它互聯網資源整理而成。如有侵權請及時聯繫我。

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