2010-02-25 77 views
4

我知道我應該使用準備好的語句,但我的下一個項目將使用準備好的語句,我只需要完成這個簡單的小應用程序。這個php代碼安全嗎?

所以我的問題是:

這是下面的代碼段的安全嗎?

我已經使用htmlentities和mysql_real_escape_string,因爲我認爲這是一個安全的選項。

//Image 
$imageInput = $_POST['Image']; 
$imageClean = htmlentities($imageInput, ENT_QUOTES, 'UTF-8'); 



//Inserts values into relevant field and creates a new row. 
mysql_query("UPDATE ***** SET image='" . mysql_real_escape_string($imageClean) . "'  WHERE id=" . mysql_real_escape_string($idClean) . ""); 

添加代碼爲$ idClean是:

//Id to change 
if(ctype_digit($_POST['testimonial'])) 
{ 
    $idInput = $_POST['testmonial']; 
    $idClean = htmlentities($idInput, ENT_QUTOES, 'UTF-8'); 
} 

感謝您的幫助。

p.s如果你可以建議一些補充,那就太好了。

+3

認爲當$ idclean會發生什麼=「1或1 = 1」 – Piskvor 2010-02-25 10:19:09

+0

&Piskvor我應該使用if(cytpe_digit)作爲$ idClean嗎? – 2010-02-25 10:23:14

+1

@Oliver Bayes-Shelton:假設'id'是一個整數,我會去(int)$ idClean – Piskvor 2010-02-25 10:24:31

回答

3

您應該只在輸出點應用實體轉義 - 在數據庫插入之前轉義數據沒有任何價值。也就是說,你正在用mysql_real_escape_string來做正確的事情。

除此之外,正如@Piskvor所說,idClean變量存在潛在的問題。 (難道這被轉換爲例如一個int?)

您可以使用下面的例子:

mysql_real_escape_string(intval($idClean)) 
+0

你能解釋一點關於實體轉義嗎?我該怎麼做呢? – 2010-02-25 10:22:07

+0

我可以使用: // ID改變 如果(ctype_digit($ _ POST [ '證明'])){ \t $ idInput = $ _POST [ '證言法']; \t $ idClean = htmlentities($ idInput,ENT_QUTOES,'UTF-8'); } – 2010-02-25 10:25:08

+1

-1你不需要在一個整數上運行mysql_real_escape_string(),你是多餘的。 – rook 2010-02-25 16:21:30

2

$ idClean從哪兒來?

另一個$ _POST?它應該是一個整數,不是嗎?

不做HTML清理就可以了,只是$idClean = (int)$_POST['id']; ......將「力」它是一個整數,「殺」所有可能的XSS/SQL注入(只爲$ idCelan我的意思)

而在一般說起來,沒有一個最好的方式來消毒投入;全部取決於約什麼輸入應該包含,這將是存儲未來將如何使用

編輯:在您對middaparka回答發表評論後,我想$ idClean來自表單(可能是隱藏的輸入)。

如果你想阻止這種形式的使用,我建議你添加另一個隱藏的字段$ idclean散列,然後在進程頁面檢查散列,看看是否有人更改了手動ID(如果你不這樣做)

這通常是一個錯誤的設計在用戶管理,不知道你的行爲。

1

假設$ _POST ['Image']是一個URI,否。有人可以使用javascript:scheme提交URI並導致其他人運行任意JavaScript。

+0

不需要$ _POST ['Image']只是文件名.extension – 2010-02-25 10:27:53

4

取決於您的$idClean是多麼乾淨。

WHERE id=" . mysql_real_escape_string($idClean) . " 

mysql_real_escape_string only prepends backslashes to \x00, \n, \r, \, ', " and \x1a,但它不會停止使用而不是mysql_real_escape_string

$idClean = "1 OR 1=1 AND POSSIBLY OTHER SQL STATEMENTS" 

攻擊你應該將其轉換爲一個int。

+0

+1非常好。你完全正確。除了你注入的sql是無效的。攻擊者會使用子選擇來利用這個。 – rook 2010-02-25 16:25:50

0

「Image」和ID的預期字符範圍是什麼?雖然轉義輸入是一個好主意,但您應該始終檢查輸入是否僅包含給定數據類型的合法字符。例如

if (preg_match("/\w(\w|\\.){0,31}/", $imageInput) && preg_match("/\d{1,12}/", $idClean)) { 
// do database update 
} else { 
// invalid input, let the user know! 
} 

上面的$ imageInput上的正則表達式應該只允許一個帶有字母數字,下劃線和句號的圖像名稱。長度爲1到32個字符(您希望將其與您的數據庫定義相匹配)。沒有其他字符允許。我做了記憶中的正則表達式,如果轉義不正確,請原諒我,但使用正則表達式來消除已知的良好輸入的原則是一條路。

數據庫安全性不是您需要考慮的安全性的唯一方面。考慮跨站點腳本(XSS)。如果用戶輸入圖像名稱如下:javascript:alert('abc');那麼當你將其顯示回用戶時,它將在瀏覽器中執行!

0

正如之前所說的,您遇到了與id=xyz有關的問題。但不是將它轉換爲一個整數在PHP我也將它作爲字符串文字傳遞,有兩個原因:

  • 您可以更改id字段的類型,而無需觸摸該代碼的特定部分。一個id並不總是必須是一個整數。
  • php整數的取值範圍(尤其是最大值)可能小於字段定義的類型。

connection charset影響mysql_real \ escape_string()的行爲。因此,您應該將連接資源作爲第二個參數傳遞給mysql_real \ escape_string()。

在插入數據之前是否使用htmlentities()取決於您想要實現的內容。如果您需要將數據作爲html/utf-8以外的其他數據,您必須將其轉換回來。但由於這是不完全安全相關....有它自己的方式;-)

$mysql = mysql_connect('..', '..', '..'); 
//... 
$query = sprintf(" 
    UPDATE 
    ***** 
    SET 
    image='%s' 
    WHERE 
    id='%s' 
    ", 
    mysql_real_escape_string($imageClean, $mysql), 
    mysql_real_escape_string($id, $mysql) 
); 

哦,順便說一句:強制性暗示準備的語句:http://docs.php.net/pdo.prepared-statements