2008-09-21 137 views

回答

227

當涉及到數據庫查詢時,總是嘗試使用準備好的參數化查詢。 mysqliPDO庫支持這一點。這比使用轉義函數如mysql_real_escape_string更安全。

是的,mysql_real_escape_string實際上只是一個字符串轉義函數。這不是一個神奇的子彈。它所要做的就是轉義危險字符,以便它們可以安全地在單個查詢字符串中使用。但是,如果您沒有事先清理您的輸入,那麼您將很容易受到某些攻擊媒介的攻擊。

想象一下以下SQL:

$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']); 

你應該能夠看到,這是容易被利用。
想象id參數包含了常見的攻擊向量:

1 OR 1=1 

那裏面有沒有風險的字符編碼,因此它會通過直通過逃避過濾器。離開我們:

SELECT fields FROM table WHERE id= 1 OR 1=1 

這是一個可愛的SQL注入載體,將允許攻擊者返回所有行。 或者

1 or is_admin=1 order by id limit 1 

產生

SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1 

,允許攻擊者在這個完全虛構的例子返回第一個管理員的詳細信息。

雖然這些功能很有用,但必須小心使用。您需要確保所有網頁輸入在某種程度上得到驗證。在這種情況下,我們看到我們可以被利用,因爲我們沒有檢查我們用作數字的變量,實際上是數字。在PHP中,您應該廣泛使用一組函數來檢查輸入是整數,浮點數,字母數字等。但是對於SQL,請注意準備語句的大部分值。如果數據庫函數已知道1 OR 1=1不是有效的文字,則上述代碼將是安全的。對於htmlspecialchars()。這是它自己的一個雷區。

在PHP中存在一個真正的問題,它具有不同的與html相關的轉義函數的全部選擇,並且沒有明確的指導哪些函數會做什麼。首先,如果你在一個HTML標籤內,你真的很麻煩。看看

echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />'; 

我們已經是一個HTML標記內,因此我們不需要<或>做任何危險。我們的攻擊媒介可能僅僅是javascript:alert(document.cookie)

現在產生的HTML看起來像

<img src= "javascript:alert(document.cookie)" /> 

攻擊直通得到。

它變得更糟。爲什麼?因爲htmlspecialchars(當這樣調用時)只能編碼雙引號而不是單引號。所以,如果我們有

echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />"; 

我們的邪惡攻擊者現在可以注入全新的參數

pic.png' onclick='location.href=xxx' onmouseover='... 

給我們

<img src='pic.png' onclick='location.href=xxx' onmouseover='...' /> 

在這種情況下,也沒有神奇的子彈,你只需要自己調整輸入。如果你嘗試過濾出不好的字符,你肯定會失敗。採取白名單的方式,只允許通過良好的字符。查看XSS cheat sheet,瞭解各種向量可能的示例

即使您在HTML標記之外使用htmlspecialchars($string),仍然容易受到多字節字符集攻擊媒介的攻擊。

您可以最有效地使用mb_convert_encoding和htmlentities的組合,如下所示。

$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8'); 
$str = htmlentities($str, ENT_QUOTES, 'UTF-8'); 

即使這樣也會讓IE6容易受到攻擊,因爲它處理UTF。但是,在IE6使用率下降之前,您可能會回退到更有限的編碼,例如ISO-8859-1。

爲了更深入的研究,多字節的問題,請參見https://stackoverflow.com/a/12118602/1820

+23

這裏唯一遺漏的是,DB查詢的第一個例子...一個簡單的intval()將解決注入。需要數字而不是字符串時,始終使用intval()代替mysqlescape ...()。 – 2009-04-09 03:15:58

+10

並記住使用參數化查詢將允許您始終將數據視爲數據而不是代碼。儘可能使用PDO等庫並使用參數化查詢。 – Cheekysoft 2009-04-14 10:47:37

+1

優秀的答案! – joedevon 2009-06-12 07:06:02

9

除了Cheekysoft的出色答卷:

  • 是的,他們會保證你的安全,但前提是要使用它們絕對正確。錯誤地使用它們,你仍然會很脆弱,並且可能還有其他問題(例如數據損壞)
  • 請改用參數化查詢(如上所述)。您可以通過例如PDO或通過包裝PEAR DB
  • 請確保magic_quotes_gpc和magic_quotes_runtime始終處​​於關閉狀態,並且永遠不會意外打開,甚至不會短暫地打開。這是由PHP的開發早期和深度誤導試圖阻止安全問題(它破壞數據)

是不是真的爲了防止HTML注入(如跨站腳本)銀彈,但你可以如果您使用庫或模板系統輸出HTML,則可以更輕鬆地實現它。閱讀有關如何正確轉義事物的文檔。

在HTML中,事情需要根據上下文以不同的方式轉義。對於放入Javascript的字符串尤其如此。

3

我肯定會與上述職位同意,但我有一個小的事情在回答增加Cheekysoft的回答,特別是:

當涉及到數據庫查詢, 總是試圖用準備 參數化查詢。 mysqli和PDO庫支持這一點。這是 比使用轉義 功能如 mysql_real_escape_string更安全。

是的,mysql_real_escape_string是 有效只是一個字符串轉義 函數。這不是一個神奇的子彈。 它會做的只是逃脫危險 字符,以便它們可以安全地在單個查詢字符串中使用 。 但是,如果您沒有事先對您的 輸入進行消毒,那麼您將成爲 容易受到某些攻擊媒介的攻擊。

想象以下SQL:

$結果= 「選擇FROM表 字段WHERE ID = 」 .mysql_real_escape_string($ _ POST [ 'ID']);

您應該能夠看到這是易受攻擊的 。試想ID 參數包含了常見的攻擊向量 :

1 OR 1 = 1

那裏面有沒有風險的字符來 編碼,因此它會直接 通過逃避過濾器。離開 我們:

選擇字段FROM表WHERE ID = 1 OR 1 = 1

我編寫了一個小巧的功能,我把我的數據庫類,將去掉任何心不是一個數量。它使用了preg_replace,所以概率更優化的一點作用,但在緊要關頭的作品...

function Numbers($input) { 
    $input = preg_replace("/[^0-9]/","", $input); 
    if($input == '') $input = 0; 
    return $input; 
} 

因此,而不是使用

$結果=「選擇字段FROM表WHERE ID =「.mysqlrealescapestring(」1 OR 1 = 1「);

我會用

$結果= 「選擇字段FROM表WHERE ID =」。數字(「1或1 = 1」);

,它會安全地運行查詢從表

選擇字段WHERE ID = 111

當然,這只是停止了它無法顯示正確的行,但我不認爲是誰試圖注入到您的網站的SQL是一個大問題;)

2

這個難題的一個重要部分是上下文。

SELECT fields FROM table WHERE id='".mysql_real_escape_string($_GET['id'])."'" 

導致:

SELECT fields FROM table WHERE id='1 OR 1=1' 

這是無效的,如果你在引用查詢的每個論點有人發送 「1 OR 1 = 1」 的ID是沒有問題的。由於您正在轉義字符串,所以輸入無法脫離字符串上下文。我已經測試過MySQL的版本5.0.45,並且使用整數列的字符串上下文不會導致任何問題。

1
$result = "SELECT fields FROM table WHERE id = ".(INT) $_GET['id']; 

在64位系統上工作良好,甚至更好。儘管如此,請注意您的系統在處理大量數據時的限制,但對於數據庫ID來說,這在99%的時間內很有效。

您應該使用單個函數/方法來清理您的值。即使這個函數只是mysql_real_escape_string()的包裝器。爲什麼?因爲有一天,如果發現利用您的首選清理數據的方法,您只需將其更新到一個地方,而不是在系統範圍內找到並替換。

-3

爲什麼,哦爲什麼,你會而不是包括用戶輸入在您的SQL語句周圍引號?似乎很愚蠢的不!包括你的sql語句中的引號會使「1或1 = 1」成爲毫無結果的嘗試,不是嗎?

所以現在,你會說,「如果用戶在輸入中包含引號(或雙引號)會怎麼樣?」

好吧,簡單的解決方法:只需刪除用戶輸入的報價。例如:。現在,無論如何,在我看來,用戶輸入將是安全的...