2013-08-05 29 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

没有人知道您的代码中确定了什么以及将来如何更改它。你的问题和答案都没有提到它。 –