若是經過網頁接收用戶輸入,然後再把這些數據插入到數據庫中,那麼你可能就會碰到 SQL 注入式攻擊。本節簡要介紹如何防範這種攻擊,確保腳本和 MySQL 語句的安全性。mysql
注入式攻擊每每發生在要求用戶輸入時,好比說要求他們輸入本身的名字,可是他們卻輸入了一段 MySQL 語句,不知不覺地運行在數據庫上。sql
永遠不要相信用戶所提供的數據,只有在驗證無誤後,才能去處理數據。一般,利用模式匹配來實現。在下面這個範例中,username(用戶名)被限定爲字母數字混合編制的字符串,再加上下劃線,長度限定爲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"; }
爲了暴露問題所在,請考慮下面這段代碼:安全
// 本應該的輸入 $name = "Qadir'; DELETE FROM users;"; mysql_query("SELECT * FROM users WHERE name='{$name}'");
函數調用本來會從 users 表中獲取一個記錄。name 列與用戶所指定的名字所匹配。在通常狀況下,$name 會包含字母數字混合編制的字符,或許還包含空格,such as the string ilia. 但這裏,爲 $name 添加了一個全新的查詢,數據庫調用就變成了災難:注入的 DELETE 查詢會刪除 users 表中全部的記錄。markdown
幸運的是,若是使用 MySQL,mysql_query()
函數不容許堆疊查詢,或在一個函數調用中執行多個查詢。若是嘗試使用堆疊查詢,則調用會失敗。函數
然而,有些 PHP 數據庫擴展,好比 SQLite 或 PostgreSQL,卻能很好地執行堆疊查詢,可以執行一個字符串中所提供的全部查詢,從而形成嚴重的安全隱患。code
使用 PERL 或 PHP 這樣的腳本語言,能夠很巧妙地處理轉義字符。MySQL 針對 PHP 的擴展也提供了mysql_real_escape_string()
,能夠將輸入的字符轉義爲MySQL所特有的字符。ip
if (get_magic_quotes_gpc()) { $name = stripslashes($name); } $name = mysql_real_escape_string($name); mysql_query("SELECT * FROM users WHERE name='{$name}'");
爲了解決 LIKE 困境,經常使用的轉義機制必須將 用戶所輸入的 %
和 _
字符轉義爲字面值。使用 addcslashes()
能爲你指定一個轉義字符範圍。字符串
$sub = addcslashes(mysql_real_escape_string("%something_"), "%_"); // $sub == \%something\_ mysql_query("SELECT * FROM messages WHERE subject LIKE '{$sub}%'");