2013-01-14 21 views
1

我熟悉準備好的語句,我知道它們是防止MySQL注入的最佳實踐。但我不知道這個PHP/MySQL的聲明可能是如何在注入攻擊的風險:MySQL注入查詢

$result = mysqli_query($db,"SELECT name FROM users WHERE id = '".$_POST['name']."';"); 

在我看來,像來自用戶的輸入將被包含在單引號內。你可以在一個mysqli_query聲明中執行多個查詢嗎?

而且,使上述安全一樣簡單,因爲這...

$result = mysqli_query($db,"SELECT name FROM users WHERE id = '".mysqli_real_escape_string($_POST['name'])."';"); 
+0

看看這個:http://www.unixwiz.net/techtips/sql-injection.html – mcalex

+0

http://xkcd.com/327/ – Stu

+0

到目前爲止答案沒有解決這個問題:這似乎是關鍵 - 你可以在一個mysqli_query語句中執行多個查詢嗎? – Randy

回答

1

在我看來,像來自用戶的輸入將被包含在單引號內

那就除非您在張貼name單引號,這樣可以讓你打出來的引號。例如,發佈名稱爲:

' or 1 or ' 

WHERE子句變爲:

WHERE id = '' or 1 or ''; 

這將匹配和檢索所有表中的行,因爲or 1部分。正如你所看到的,它打破了引號來注入一些SQL,然後它返回到引號使查詢有效。

你能在一個mysqli_query聲明中執行多個查詢嗎?

不,但如果它與mysqli_multi_query一起執行,那麼你可以添加多個查詢到最後。

使上述安全就像mysqli_real_escape_string一樣容易?

一般來說是的,但一份聲明中會更好。使用轉義的WHERE條款將成爲(使用上面的示例所示):

WHERE id = '\' or 1 or \''; 

此不再脆弱,因爲引號無法爆發的,如果name嚴格匹配' or 1 or '將只匹配行這顯然不太可能。

3

在我看來,像來自用戶的輸入將被包含在單引號內

所有攻擊者所要做的就是在POST數據名稱中加入一個單引號,並且它將不再存在。

name=' OR 1=1 

而且,使上述安全一樣簡單,因爲這

這看起來不錯...但它傷害了我的眼睛。使用預準備的語句他們更容易閱讀,然後通過串聯字符串來構建SQL。

+1

'UNION SELECT password AS name FROM users WHERE id =' –

0

如果我通過了以下值$_POST['name'],該怎麼辦?

'; DELETE FROM users WHERE name <> ' 

我會閉合第一單引號,然後將其只是有在年底,這將由單引號的原始查詢被關閉一個公開報價的破壞性查詢。

你的第二個查詢很好。雖然你真的應該如果你使用mysqli你應該總是使用這樣的SQL佔位符的方法來考慮使用預處理語句(由mysqli的支持)

+1

這是一個常見的誤解(可能是由於該漫畫),如果用'mysqli_multi_query()'執行,你只能附加一個查詢。您仍然可以利用它,但不能添加新的查詢。 – MrCode

+0

@MrCode是啊,這是正確的mysqli的。 –

0

的。逃避功能是困難的。

$stmt = $db->prepare("SELECT name FROM users WHERE id = ?"); 
$stmt->bind_param('i', $_POST['name']); 
$stmt->execute(); 

如果你不明白這裏的風險,你真的需要在一般SQL injection attacks讀了,讀什麼automated hacking tools可以做那些沒有足夠謹慎。

+0

我正在使用mysqli,並且我從不準備使用準備好的語句,因爲它們不便於使用,不足以用於保護,並且[雖然只是在理論上]較慢。 –

+0

請您澄清一下嗎?準備好的語句如何「不足」,並且比將'mysqli_real_escape_string'中的每個字符串包裝起來更麻煩?你似乎建議在你的其他評論中使用'bind_param',所以你在說什麼? – tadman

1

基本交代:

如果你只需插入$_POST['name']到查詢按你的第一個例子中,生成的SQL字符串,如果name變量包含一個單引號字符是無效的。

這會立即干擾任何名爲O'Brien或類似的人。

但是,這可以被黑客利用,黑客可以修改他的「名稱」以在單引號之後包含有效的SQL代碼。這可以是任何有效的SQL,允許黑客對數據庫執行任何操作或從中查詢任何內容。他所能做的事情取決於代碼中的其他因素,但足以說明,即使在最好的情況下,他也可以做​​一些非常具有破壞性的事情。

要回答你的第二個問題:是的。使用mysqli_real_escape_string()轉義將緩解此問題。

然而,走一步算一步,你可能也想使用準備好的查詢,這是mysqli擴展的特性進行調查。因爲它避免了使用那個討厭的長mysqli_real_escape_string()函數名到處都是這樣可以使你的代碼很多整潔。它還具有其他好處,例如改進的查詢緩存。

希望幫助回答這個問題。

+0

爲了mysqli_bind_param(),避免令人討厭的長mysqli_real_escape_string()函數,該函數肯定會縮短整個單詞;) –