概述
??sql注入就是利用某些數據庫的外接接口將用戶數據插入到實際的接口語言當中,從而達到入侵數據庫乃至操作系統的目的。在接口領域,我們永遠不要信任用戶的輸入,我們必須認定用戶輸入的數據都是不安全的,我們都需要對用戶輸入的數據進行過濾處理。沒有(運行時)編譯,就沒有注入。所以從根本上防止上述類型攻擊的手段,還是避免數據變成代碼被執行,時刻分清代碼和數據的界限。而具體到sql注入來說,被執行的惡意代碼是通過數據庫的sql解釋引擎編譯得到的,所以只要避免用戶輸入的數據被數據庫系統編譯就可以了。
??與其他數據庫不同,接口可以運行在不同的sql mode(sql服務器模式)下,并且可以為不同客戶端應用不同模式。這樣每個應用程序可以根據自己的需求來定制服務器的操作模式。模式定義mysql應支持哪些sql語法,以及應執行哪種數據驗證檢查。這有點類似于apache配置不同級別的錯誤日志,報告哪些錯誤,又不報告哪些錯誤。
SQL注入
1.注入實例
//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表,你的數據被破壞了。
2.防止sql注入
方法一
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服務器模式
1.sql模式語法
#查看當前sql模式 select?@@sql_mode; #查看當前sql模式 SELECT?@@session.sql_mode; #修改當前sql模式 SET?[SESSION][GLOBAL]?sql_mode='modes';
-
其中session選項表示只在本次連接生效;而global表示在本次連接不生效,下次連接生效。
-
也可以使用“–sql-mode=’modes’”,在MySQL啟動時候設置sql_mode。
-
可以在接口中設置。
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_FIELD_OPTIONS, NO_AUTO_CREATE_USER。
【相關推薦】
1.?接口
2.?接口
3. 接口