2011-12-19 29 views
8

我聽到有人說(關於C#/ SQL Server,但也與PHP/MySql有關):不要手動轉義字符串 - 使用存儲過程代替爲什麼mysql_real_escape_string()不應該避免任何SQL注入?

好的,我可以接受這個建議,但爲什麼?很多人說(包括對SO)mysql_real_escape_string()是相當不夠的,mysql_real_escape_string()是好的,mysql_real_escape_string()是第一種保護方式。

爲什麼?有沒有mysql_real_escape_string()可能會失敗的情況?至少有一個...我不需要太多:)

+8

這是最大的弱點是_you_可以忘記使用它! –

+0

您會發現MySQL中存儲過程的使用比在SQL Server中使用的少,但使用預準備語句通常是PHP/MySQL API鼓勵使用的。 –

+1

我從來沒有使用過mysql_real_escape_string()的任何問題。 我認爲人們說使用商店程序,而不是因爲有機會忘記使用mysql_real_escape_String()。 – Khronos

回答

1

只是爲了解信息: mysql_real_escape_string()不逃脫%_。這些是MySQL中的通配符,如果與LIKE, GRANT, or REVOKE結合使用。

3

有兩件事情可以去錯mysql_real_escape_string

  • 你可以忘記如果你使用一些特定的多字節連接編碼使用它
  • ,而您與SET NAMES,而不是設置這些編碼mysql_set_charset爲是正確的,它仍然可以讓你容易受到

更新:

  • 您是使用UTF-8安全(雖然這並不意味着你應該繼續使用SET NAMES!)
  • 有關說明,請參閱here
+0

你能給我一個第二點的例子嗎?我用UTF8使用SET NAMES,它應該是安全的嗎? – markzzz

+0

@markzzz:查看更新回答 – Jon

+0

第三件事:你可以記得使用它,當不在引號內時這樣做。 – Cheekysoft

0

mysql_real_escape_string()可能無法清理輸入。 由於mysql_real_esacpe_string()在清理字符串時需要考慮字符集。 有問題。您可以通過mysql_query函數發送查詢來更改字符,以更改連接的字符集。但是,mysql_real_escape_string()忘記了您正在使用的設置,並且它會不正確地轉義某些字符。

另一件事是不斷手動調用它。即使將它封裝在一個函數中也是P.I.T.A.因爲這意味着你必須創建一些你自己的數據庫包裝/數據庫抽象層,以便能夠自動調用mysql_real_escape_string()

這就是爲什麼我們在PHP中使用PDO,它可以幫助我們減輕上述所有情況,並且您可以使用參數化預處理語句,其中是處理重複查詢以改變數據的首選方式。

準備語句,綁定輸入變量,它將根據所使用的數據庫驅動程序和連接的字符集來清理輸入。它代碼少,完全安全。

+0

沒有什麼是完全安全的,甚至PDO。即它沒有使用表格和列名稱作爲參數的機制,所以您最終都會使用手動衛生來防止注入,即使使用PDO也是如此。 – brezanac

+0

@holodoc - 如果您發現自己需要通過PDO綁定列名和表名,這意味着您從用戶輸入中接收到列/表名,這進一步意味着您所做的方式根本不對。否則,如果你已經將你的col./tables編碼到你的DBAL數組中,那麼需要額外檢查它們是否導致sql錯誤? PDO對於保存用戶的輸入非常安全。 mysql_real_escape有一些缺陷,他們已被指出。 –

+0

爲什麼使用動態列名和表名意味着那些是從用戶輸入中檢索的?在很多情況下,通過簡單流量控制來確定表/列名稱的確定方式。 – brezanac

9

當mysql_real_escape_string FAIL

$sql = "SELECT * FROM users WHERE id=" + mysql_real_escape_string($_GET['id']); 

如果$_GET['user_id']設置爲1 OR 1 = 1,沒有特殊字符,它不是過濾。

結果:返回所有行。

它變得更糟。怎麼樣...如果$_GET['user_id']設置爲1 OR is_admin = 1

該函數僅用於在單引號內部使用。

+0

我經常在野外看到這個 – Cheekysoft

+0

是啊!通常情況下,如果我對一個int進行表示,我會檢查$ _GET ['user_id']是否爲int!是的,當然,我應該使用PDO來避免這些檢查... – markzzz

+0

好吧,這也會導致PDO失敗,無論如何......:O – markzzz

0

只有一個約mysql_real_escape_string()和SQL注入的東西 -

前者沒有絲毫關係到後者。

儘管聽起來似是而非,但沒有什麼比這更真實的了。

這裏有兩個報表證明它

  1. 你必須只逃脫引用的字符串,因爲該功能可以幫助沒有別的。
  2. 實際上,您必須每轉換爲字符串,您將添加到查詢中,即使是最安全的一個。只是因爲它可能包含一些特殊字符,從而打破查詢(就像一個意外事件,而不是惡意陰謀)。

因此,在適用的情況下,無論如何,無論出現什麼危險或恐懼,都必須使用此功能。而在其他任何情況下,這無濟於事。

我唯一需要補充的是準備好的陳述並不提供完整的保護。這裏是解釋和建議:https://stackoverflow.com/a/8255054/285587