SQL注入(SQL Injection)
所謂SQL注入式攻擊,就是攻擊者把SQL命令插入到Web表單的輸入域或頁面請求的查詢字符串,欺騙服務器執行惡意的SQL命令。攻擊者通過web請求提交帶有影響正常SQL執行的參數(arlen’ OR ‘1’=’1),服務端在執行SQL時參數的特殊性影響了原本的意思(select * from table where user=’arlen\’ OR \’1\’=\’1’;),執行了非預期的操作(select * from table where user=’arlen’ OR ‘1’='1’),從而是攻擊者獲取到了其他用戶的信息或者對服務造成了攻擊。
SQL注入操作簡單,危害嚴重,現在也有比較成熟的防范措施,但是往往因為開發人員操作不當(例如:忘記過濾參數、不當的錯誤處理、配置失誤)而產生風險,如果未被發現SQL注入漏洞並不影響任何系統功能,往往也不被察覺,一旦攻擊者發現SQL漏洞,后果就比較嚴重。
SQL注入技術原理
在大多數web接口傳入的參數最終都會反映到數據庫表中的某一字段,例如用戶登錄的例子:
后端代碼通過如下方法實現:
<?php $con = mysql_connect("localhost", "xxx", "xxx"); if (!$con) { die('Could not connect: '.mysql_error()); } $db_selected = mysql_select_db("xxx", $con); if (!$db_selected) { die('select db test failed: '.mysql_error()); } $user = $_REQUEST["user"]; $pwd = $_REQUEST["password"]; $sql = "select count(*) as count from user_info where user = '$user' AND password = '$pwd';"; $sql_query = mysql_query($sql, $con); if (!$sql_query) { die(' mysql_query failed: '.mysql_error()); } $num = 0; if (!$data = mysql_fetch_object($sql_query)) { die('mysql_fetch_object failed: '.mysql_error()); } else { $num = $data->count; } if (0 >= $num) { echo "user[$user] login failed!"; } else { echo "user[$user] login succ!"; } ?>
在后端實現是通過下面SQL來判斷用戶和密碼是否匹配:
SELECT COUNT (*) as count FROM user_info WHERE user='arlen' AND password='123456';
如果服務器沒有做過濾操作,可以令user=arlen’ or ‘1’='1來進行登錄,即便完全不知道用戶arlen對應的密碼一樣可以校驗通過,php拼裝的SQL語句為:
SELECT COUNT (*) as count FROM user_info WHERE user='arlen' or '1' = '1' AND password='123456';
這樣只要user_info表中有數據就能通過login的校驗。
SQL注入的原理就是在正常station 字段中注入特征字符,能組合成新的SQL 語句。SQL注入學習成本低,攻擊性高,容易防范,但往往因為工作上的失誤或者測試的不足而留下漏洞。
SQL注入防御
SQL注入原理簡單易學,但防范起來卻略為復雜,本質就是防止用戶輸入的不安全參數放映到具體的SQL語句上,例如:
1. web參數過濾,只允許約定的字符出現,比如數字、字母,100%解決問題,但過於暴力;
2. 對需要拼裝SQL語句的參數做過濾,例如PHP自帶的mysql_real_escape_string()函數,修改上述代碼如下:
if (!$db_selected) { die('</br>select db test failed: '.mysql_error()); } $user = mysql_real_escape_string($_REQUEST["user"]); $pwd = mysql_real_escape_string($_REQUEST["password"]); $sql = "select count(*) as count from user_info where user = '$user' AND password = '$pwd';"; echo $sql; $sql_query = mysql_query($sql, $con);
這樣實際執行的SQL為:
select count(*) as count from user_info where user = 'arlen\' or \'1\' = \'1' AND password = '1234567';
3. 小心拼寫SQL語句,一定要注意拼接SQL字段各個字段的來源,如果是外部傳入的,根據不信任原則,一定要嚴格校驗過濾;
4. 設置Mysql權限,只給訪問數據庫的web應用功能所需的最低權限帳戶,這種只能降低損失,並不能避免注入;
5. 避免將數據庫的錯誤信息直接返回,對於Mysql錯誤,程序一定要識別后再做返回,避免將錯誤描述直接返回給前端。
6. 小心、細心,SQL注入最常出現在開發人員粗心時;
7. 借助SQL注入掃描工具。
SQL注入其他資料
百度百科:http://baike.baidu.com/view/3896.htm
SQL注入危害:http://www.cnblogs.com/hkncd/archive/2012/03/31/2426274.html