(017)sql注入與sql mode

概述

sql注入就是利用某些數(shù)據(jù)庫的外接接口將用戶數(shù)據(jù)插入到實際的數(shù)據(jù)庫操作語言當(dāng)中,從而達(dá)到入侵?jǐn)?shù)據(jù)庫乃至操作系統(tǒng)的目的。在安全領(lǐng)域,我們永遠(yuǎn)不要信任用戶的輸入,我們必須認(rèn)定用戶輸入的數(shù)據(jù)都是不安全的,我們都需要對用戶輸入的數(shù)據(jù)進(jìn)行過濾處理。沒有(運行時)編譯,就沒有注入。所以從根本上防止上述類型攻擊的手段,還是避免數(shù)據(jù)變成代碼被執(zhí)行,時刻分清代碼和數(shù)據(jù)的界限。而具體到SQL注入來說,被執(zhí)行的惡意代碼是通過數(shù)據(jù)庫的SQL解釋引擎編譯得到的,所以只要避免用戶輸入的數(shù)據(jù)被數(shù)據(jù)庫系統(tǒng)編譯就可以了。
??與其他數(shù)據(jù)庫不同,MySQL可以運行在不同的SQL Mode(SQL服務(wù)器模式)下,并且可以為不同客戶端應(yīng)用不同模式。這樣每個應(yīng)用程序可以根據(jù)自己的需求來定制服務(wù)器的操作模式。模式定義MySQL應(yīng)支持哪些SQL語法,以及應(yīng)執(zhí)行哪種數(shù)據(jù)驗證檢查。這有點類似于apache配置不同級別的錯誤日志,報告哪些錯誤,又不報告哪些錯誤。

SQL注入

1.注入實例

//php代碼
$unsafe_variable = $_POST['user_input'];   
mysql_query("INSERT INTO `table` (`column`) VALUES ('{$unsafe_variable}')");  

當(dāng)post中代碼如下時候:

value'); DROP TABLE table;--

查詢代碼變成

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

這樣會直接刪除table表,你的數(shù)據(jù)被破壞了。

2.防止sql注入

方法一
prepareStatement+Bind-Variable:SQL語句和查詢的參數(shù)分別發(fā)送給數(shù)據(jù)庫服務(wù)器進(jìn)行解析。
對于php來說有兩種實現(xiàn)方式。

//使用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擴(kuò)展-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
}  

方式二
對查詢語句進(jìn)行轉(zhuǎn)義(最常見的方式):使用應(yīng)用程序提供的轉(zhuǎn)換函數(shù)。
|應(yīng)用|函數(shù)|
|--------|
|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()|

方式三
使用自己定義函數(shù)進(jìn)行校驗:其本質(zhì)上還是對輸入非法數(shù)據(jù)進(jìn)行轉(zhuǎn)義和過濾。
輸入驗證可以分為:1.整理數(shù)據(jù)使之有效;2.拒絕已知的非法輸入;3.只接收已知的合法輸入。

方式四
使用存儲過程。
存儲過程參見: (9)mysql中的存儲過程和自定義函數(shù)

sql服務(wù)器模式

1.sql模式語法

#查看當(dāng)前sql模式
select @@sql_mode;
#查看當(dāng)前sql模式
SELECT @@session.sql_mode;
#修改當(dāng)前sql模式
SET [SESSION][GLOBAL] sql_mode='modes';
  • 其中session選項表示只在本次連接生效;而global表示在本次連接不生效,下次連接生效。
  • 也可以使用“--sql-mode='modes'”,在MySQL啟動時候設(shè)置sql_mode。
  • 可以在配置文件中設(shè)置。

2.sql_mode常用值

ONLY_FULL_GROUP_BY:
對于GROUP BY聚合操作,如果在SELECT中的列,沒有在GROUP BY中出現(xiàn),那么這個SQL是不合法的,因為列不在GROUP BY從句中。

NO_AUTO_VALUE_ON_ZERO:
該值影響自增長列的插入。默認(rèn)設(shè)置下,插入0或NULL代表生成下一個自增長值。如果用戶 希望插入的值為0,而該列又是自增長的,那么這個選項就有用了。

STRICT_TRANS_TABLES:
在該模式下,如果一個值不能插入到一個事務(wù)表中,則中斷當(dāng)前的操作,對非事務(wù)表不做限制。

NO_ZERO_IN_DATE:
在嚴(yán)格模式下,不允許日期和月份為零。

NO_ZERO_DATE:
設(shè)置該值,mysql數(shù)據(jù)庫不允許插入零日期,插入零日期會拋出錯誤而不是警告。

ERROR_FOR_DIVISION_BY_ZERO:
在INSERT或UPDATE過程中,如果數(shù)據(jù)被零除,則產(chǎn)生錯誤而非警告。如 果未給出該模式,那么數(shù)據(jù)被零除時MySQL返回NULL。

NO_AUTO_CREATE_USER:
禁止GRANT創(chuàng)建密碼為空的用戶。

NO_ENGINE_SUBSTITUTION:
如果需要的存儲引擎被禁用或未編譯,那么拋出錯誤。不設(shè)置此值時,用默認(rèn)的存儲引擎替代,并拋出一個異常。

PIPES_AS_CONCAT:
將"||"視為字符串的連接操作符而非或運算符,這和Oracle數(shù)據(jù)庫是一樣的,也和字符串的拼接函數(shù)Concat相類似。

ANSI_QUOTES:
啟用ANSI_QUOTES后,不能用雙引號來引用字符串,因為它被解釋為識別符。

說明

ORACLE的sql_mode設(shè)置等同:PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, NO_KEY_OPTIONS, NO_TABLE_OPTIONS, NO_FIELD_OPTIONS, NO_AUTO_CREATE_USER。

參考

1.sql注入

http://www.zhihu.com/question/22953267
http://blog.csdn.net/agoago_2009/article/details/37884797

2.sql模式

http://tech.it168.com/a2012/0822/1388/000001388401.shtml
http://c.biancheng.net/cpp/html/1471.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容