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的處理
* 參數類型校驗