本問題已經有最佳答案,請猛點這里訪問。
這是否足以避免SQL注入?
這里只需要mysql_real_escape_string()方法。在將數據插入數據庫之前,不應該執行htmlentities()或urlencode()。這些方法通常是在呈現您提供給用戶的視圖期間編寫的代碼。
避免SQL注入的更好方法是使用準備好的語句。
資源:
php.net-用pdo編寫語句
關于同一主題:
php:mysql-real-escape-string是否足以清除用戶輸入?
+準備好的報表。在正確的情況下,它們也可以幫助提高性能。
+準備好的報表1份
<3個準備好的聲明:)
我認為您混淆了兩個安全問題:SQL注入和跨站點腳本(XSS)。
如果在發送到SQL數據庫的SQL查詢中使用了未正確清理的用戶輸入,則網站容易受到SQL注入的攻擊。例如,此代碼引入了一個SQL注入漏洞:
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . $_POST['postmessage'] ."')");
這個問題很容易通過使用像mysql_real_escape_string這樣的函數來轉義用戶輸入來解決:
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string($_POST['postmessage']) ."')");
這就是您需要做的全部工作,但最棘手的部分是記住要為SQL語句中使用的每一個用戶輸入完成這項工作。
當用戶輸入在發送到客戶機的HTML中使用時,網站容易受到跨站點腳本攻擊。例如,此代碼引入了一個XSS漏洞:
echo"" . $_POST['postmessage'] ."";
通過使用類似于htmlspecialchars的函數來轉義用戶輸入,可以修復XSS漏洞:
echo"" . htmlspecialchars($_POST['postmessage']) ."";
同樣,這很容易做到,但很容易被遺忘。
通常,將用戶輸入放在數據庫中以便在以后發送HTML時使用的輸入保存為未修改的。也就是說,只使用mysql_real_escape_string。但是,您可以轉義用戶輸入以防止XSS,然后轉義XSS安全字符串以防止SQL注入:
mysql_query("INSERT INTO postmessages (postmessage) VALUES ('" . mysql_real_escape_string(htmlspecialchars($_POST['postmessage'])) ."')");
好處是,在將值寫入HTML之前,不需要記住使用htmlspecialchars從數據庫中轉義值。缺點是一些值可能需要使用不同的函數進行轉義。例如,用戶名可能與htmlspecialchars一起轉義,但"postmessage"可能允許bbcode、markdown或html的子集。如果您對所有輸入進行轉義以防止XSS,那么您將需要使用htmlspecialchars_decode等工具從數據庫中取消對值的scape。
一個問題是,取消轉義字符串的轉義并不總是返回原始字符串(unescape(escape($orig))不一定與$orig相同)。即使使用htmlspecialchars和htmlspecialchars_decode,使用不同的引號樣式也會導致此問題。另一個例子是,如果使用了strip_tags,那么信息將無法恢復地被刪除;您將無法撤消strip_tags。因此,許多開發人員選擇使用mysql_real_escape_string只將值保存到數據庫中,而htmlspecialchars則從數據庫中準備一個字符串以用于HTML。
使用準備好的語句,更清晰地查看,并且一旦掌握了它的竅門,可能更容易處理,這不是更好嗎?
@施樂:當然。準備好的語句使一致地轉義用戶輸入更加容易。然而,在回答OP的問題時,我想確保他/她理解使用mysql_real_escape_string或某些db轉義機制和htmlentities或某些xss轉義機制的原因。
是的,但不使用mysql_real_escape_string()是有原因的。首先,打字很痛苦。其次,你必須記住每次都要使用它。第三,它會使代碼變得丑陋。第四,你必須記住引用你的字符串。第五,以這種方式在數據庫中插入blob更困難。
從長遠來看,學習PDO將使你的生活變得更好。學習起來比簡單使用mysql_real_escape_string()更困難,但是長期的好處超過了學習曲線帶來的不便。
您還應該確保在插入代碼的地方使用"around"。
例如,如果你這樣做
$_POST['userid'] = mysql_real_escape_string($_POST['userid']);
mysql_query('SELECT * FROM user WHERE userid = '. $_POST['userid']);
mysql-real-escape-string沒有任何幫助。這是因為"$u post['userid']沒有被包圍"。
所以你應該這么做
$_POST['userid'] = mysql_real_escape_string($_POST['userid']);
mysql_query('SELET * FROM user WHERE userid = \''. $_POST['userid'] .'\'');
相反。
所以在變量上使用mysql-real-escape-string并不意味著它們在任何查詢中都是安全的。
另一種方法是使用準備好的語句。