2013-08-05 55 views
0

作爲新手,我遵循PHP MySQL教程,建議使用常規MySQL php函數。但是,由於我被告知PDO是更好的選擇,我一直在將我的代碼轉換爲該代碼。我只是碰到了以下問題:MySQL PDO查詢語法錯誤與?參數

$query = $uspdb->prepare("SELECT post_id, is_approved, reports FROM ? WHERE id=? AND ?"); 
    $query->bindValue(1, $table, PDO::PARAM_INT); 
    $query->bindValue(2, $id, PDO::PARAM_INT); 
    $query->bindValue(3, checkPermission("comment_moderation"),PDO::PARAM_BOOL); 
    $query->execute; 
    $result = $query->fetch(PDO::FETCH_ASSOC); 

第一行拋出以下PDO例外:

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? WHERE id=? AND ?' at line 1 

這是爲什麼?我不知道語法有什麼問題。 tutorial I'm reading告訴我應該使用bindValue或execute(array(stuff))來添加參數而不是「。$ id」。和類似的,因爲它更安全,但這不是因爲什麼原因工作。

+0

您將表名稱綁定爲'PDO :: PARAM_INT',相當肯定這是錯誤的。 –

回答

1

不幸的是,準備語句只能表示一個數據文字。 (如果模擬準備)。 因此,開發人員必須自己處理標識符--PDO爲此提供無幫助

要進行動態識別安全,一個必須遵循2個嚴格的規則:

  1. 要正確格式標識符。意思是
    • 在反引號中附上標識符。
    • 通過將它們翻倍來逃避反作用力。
  2. 驗證它是否對硬編碼白名單

格式化後,將$表變量插入查詢是安全的。所以,代碼如下:

$field = "`".str_replace("`","``",$field)."`"; 
$sql = "SELECT * FROM t ORDER BY $field"; 

然而,儘管這樣的格式就足夠了情況下,像ORDER BY,對其他大多數情況下有一個不同的排序注入的可能性:讓用戶選擇他們可以看到的表格或字段,我們可能會顯示一些敏感信息,如密碼或其他個人數據。因此,最好在允許的值列表中檢查動態標識符。這裏是一個簡單的例子:

$allowed = array("name","price","qty"); 
$key = array_search($_GET['field'], $allowed)); 
if ($key === false) { 
    throw new Exception('Wrong field name'); 
} 
$field = $allowed[$key]; 
$query = "SELECT $field FROM t"; //value is safe 
+0

如果實際上並沒有留給用戶,我是否還需要對此類輸入進行清理和白名單輸入?攻擊者是否可能將任何他們想要的東西插入這樣一個變量,或者只有當我允許用戶修改它時? 在我的代碼的$表變量也被類似處理(在$類型變量爲一個$ _GET: 開關($類型){ 案 「評論」: $表= 「site_cmt_reviews」; $ posttable =「site_review 「 突破; 默認: $表= 「site_cmt_articles」; $ posttable = 「site_article」; } – ividyon

+0

不要緊用戶輸入無關,在這裏做創建的SQL查詢它的規則一直或者,遲早會被注入 –

+0

您的交換機實際上是我正在談論的非常白名單,只是一個更長的代碼 –

0

通常情況下,我解決了我提出的問題幾秒鐘後提出的問題。

問題是您只能綁定這樣的鍵值,而不是表或列名。我將必須繼續手動插入表和列名和以前一樣:

$query = $uspdb->prepare("SELECT post_id, is_approved, reports FROM $table WHERE id=? AND ?"); 
$query->execute(array($id,checkPermission("comment_moderation"))); 
$result = $query->fetch(PDO::FETCH_ASSOC); 

如果表或列名是留給用戶自行決定,你應該通過額外的步驟來淨化它,這是詳細在你的常識的迴應上面。在我的情況下,它是以下代碼:

$type = $_GET[type]; 

switch($type) { 
    case "review": 
     $table = "site_cmt_reviews"; 
     break; 
    default: 
     $table = "site_cmt_articles"; 
} 

不過,感謝您的閱讀!

+0

等一下注射。 –

+0

因爲在我的示例中,$ table變量是由代碼確定的,並且不能被用戶更改/惡意利用,但這並不真正帶來注入風險,我想呢?儘管我猜想仍然應該建議在輸入信息時對其進行消毒。 – ividyon

+0

沒有人知道您的代碼中確定了什麼以及將來如何更改它。你的問題和答案都沒有提到它。 –