位置:首頁 > 數據庫 > MySQL教學 > MySQL SQL注入

MySQL SQL注入

如果通過網頁需要用戶輸入一些數據信息,並將其插入到MySQL數據庫,這是一個引入SQL注入安全問題的機會。這一節將學習如何防止這種情況的發生,並幫助保護腳本和MySQL語句。

通常注入是在當要求用戶輸入時,類似他們的姓名,隻是一個名字,他們給出,會在不知不覺中包含MySQL的語句會在數據庫運行。

永遠不要信任用戶提供的數據,這個過程隻有在數據驗證後,作為一項規則,這是通過模式匹配進行。在下麵的例子中,用戶名被限製在字母+數字+字符加下劃線,並在8-20個字符之間的長度 - 可以根據需要修改這些規則。

if (preg_match("/^w{8,20}$/", $_GET['username'], $matches))
{
   $result = mysql_query("SELECT * FROM users 
                          WHERE username=$matches[0]");
}
 else 
{
   echo "username not accepted";
}

為了說明問題,考慮這個片段:

// supposed input
$name = "Qadir'; DELETE FROM users;";
mysql_query("SELECT * FROM users WHERE name='{$name}'");

該函數調用從表中檢索用戶記錄,其中名稱列匹配由用戶指定的名稱。 在正常情況下,$name將隻包含字母數字字符,或可能是空格,如字符串ilia。 但在這裡,通過附加一個全新的查詢到$name,在調用數據庫變成災難:注入DELETE查詢刪除所有的用戶記錄。

幸運的是,如果使用MySQL,mysql_query()函數不允許查詢堆疊或一個函數調用執行多個查詢。如果嘗試堆疊查詢,調用失敗。

然而,其他PHP數據庫擴展,如SQLite和PostgreSQL,它們會樂意地進行堆查詢,執行一個字符串提供的查詢,並創建一個嚴重的安全問題。

防止SQL注入

可以在腳本語言,如 Perl和PHP巧妙地處理所有轉義字符。MySQL擴展為PHP提供mysql_real_escape_string()函數來轉義輸入的特殊字符。

if (get_magic_quotes_gpc()) 
{
  $name = stripslashes($name);
}
$name = mysql_real_escape_string($name);
mysql_query("SELECT * FROM users WHERE name='{$name}'");

LIKE的困境

為了解決LIKE困境,自定義的轉義機製必須把用戶提供%和_字符到常量。使用addcslashes()函數,它可以讓指定的字符轉義。

$sub = addcslashes(mysql_real_escape_string("%something_"), "%_");
// $sub == \%something\_
mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");