sql注入就是利用某些資料庫的外接介面將使用者資料插入到實際的資料庫操作語言當中,從而達到入侵資料庫乃至作業系統的目的。在安全性領域,我們永遠不要信任使用者的輸入
,我們必須認定使用者輸入的資料都是不安全的,我們都需要對使用者輸入的資料進行過濾處理。 沒有(執行時期)編譯,就沒有註入。
所以從根本上防止上述類型攻擊的手段,還是避免資料變成程式碼被執行,時時刻分清程式碼和資料的界線。而具體到SQL注入來說,被執行的惡意程式碼是透過資料庫的SQL解釋引擎編譯得到的,所以只要避免使用者輸入的資料被資料庫系統編譯就可以了。
與其他資料庫不同,MySQL可以運行在不同的SQL Mode(SQL伺服器模式)下,並且可以為不同客戶端套用不同模式。這樣每個應用程式可以根據自己的需求來客製化伺服器的操作模式。模式定義MySQL應支援哪些SQL語法,以及應執行哪種資料驗證檢查。這有點類似apache配置不同等級的錯誤日誌,報告哪些錯誤,又不回報哪些錯誤。
//php代码 $unsafe_variable = $_POST['user_input']; mysql_query("INSERT INTO `table` (`column`) VALUES ('{$unsafe_variable}')");
當post中程式碼如下:
value'); DROP TABLE table;--
查詢程式碼變成
INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')
這樣會直接刪除table表,你的資料被破壞了。
方法一
prepareStatement+Bind-Variable:SQL語句和查詢的參數分別傳送給資料庫伺服器進行解析。
對於php來說有兩種實作方式。
//使用PDO(PHP data object) $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name'); $stmt->execute(array('name' => $name)); foreach ($stmt as $row) { // do something with $row } //使用mysql扩展-mysqli $stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?'); $stmt->bind_param('s', $name); $stmt->execute(); $result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { // do something with $row }
方式二
對查詢語句進行轉義(最常見的方式):使用應用程式提供的轉換函數。
|應用|函數|
|--------| |MySQL C API | mysql_real_escape_string ()| |MySQL++|escape和quote修饰符| |PHP|使用mysql_real_escape_string()(适用于PHP4.3.0以前),之后可以使用mysqli或pdo| | Perl DBI|placeholder或quote()| |Ruby DBI|placeholder或quote()|
方式三
使用自己定義函數進行校驗:其本質上還是對輸入非法數據進行轉義和過濾。
輸入驗證可分為:1.整理資料使其有效;2.拒絕已知的非法輸入;3.只接收已知的合法輸入。
方式四
使用預存程序。
預存程序請參考: (9)mysql中的預存程序與自訂函數
#查看当前sql模式 select @@sql_mode; #查看当前sql模式 SELECT @@session.sql_mode; #修改当前sql模式 SET [SESSION][GLOBAL] sql_mode='modes';
設定檔中設定。
2.sql_mode常用值ONLY_FULL_GROUP_BY:對於GROUP BY
聚合操作,如果在SELECT中的列,沒有在GROUP BY中出現,那麼這個SQL是不合法的,因為列不在GROUP BY子句中。
NO_AUTO_VALUE_ON_ZERO:此值會影響自增長列的插入。預設設定下,插入0或NULL代表產生下一個自增長值。如果使用者 希望插入的值為0,而該列又是自增長的,那麼這個選項就有用了。
STRICT_TRANS_TABLES:在該模式下,如果一個值不能插入到一個事務表中,則中斷目前的操作,對非事務表不做限制。
NO_ZERO_IN_DATE:在嚴格模式下,不允許日期和月份為零。
NO_ZERO_DATE:設定該值,mysql資料庫不允許插入零日期,插入零日期會拋出錯誤而不是警告。
ERROR_FOR_pISION_BY_ZERO:在INSERT或UPDATE過程中,如果資料被零除,則產生錯誤而非警告。如 果未給出該模式,那麼資料被零除時MySQL傳回NULL。
NO_AUTO_CREATE_USER:禁止GRANT建立密碼為空的使用者。
NO_ENGINE_SUBSTITUTION:如果需要的儲存引擎被停用或未編譯,那麼拋出錯誤。不設定此值時,用預設的儲存引擎替代,並拋出一個異常。
PIPES_AS_CONCAT:
將"||"視為字串的連接運算元而非或運算子 ,這和Oracle資料庫是一樣的,也和字串的拼接函數Concat相似。
ANSI_QUOTES:
啟用ANSI_QUOTES後,不能用雙引號來引用字串,因為它被解釋為識別符。
說明
ORACLE的sql_mode設定等同:PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIEL_OPTIONS NO_AUTO_OPTIONS NO_US。
【相關推薦】
2. MySQL最新手冊教學
#以上是sql注入實例以及如何防sql注入的詳細內容。更多資訊請關注PHP中文網其他相關文章!