避免使用Zend_Db类进行MySQL注入

时间:2009-06-10 11:23:14

标签: php mysql zend-framework zend-db-table

我目前使用Zend_Db来管理我的查询。 我已经编写了代码,可以执行如下所示的查询:

$handle->select()->from('user_id')
                   ->where('first_name=?', $id)
                   ->where('last_name=?', $lname)

我假设Zend_Db会在没有清理输入的情况下完成此操作。 Zend会这样做吗?

另一个问题: Zend_Db会清理insert('table', $data)update个查询吗?

感谢。

7 个答案:

答案 0 :(得分:24)

我在Zend Framework中编写了很多数据库参数和引用的代码,而我是该项目的团队负责人(最高版本为1.0)。

我试图在可能的情况下鼓励最佳实践,但我必须在易用性方面取得平衡。

请注意,您始终可以检查Zend_Db_Select对象的字符串值,以了解它是如何决定引用的。

print $select; // invokes __toString() method

此外,您可以使用Zend_Db_Profiler检查由Zend_Db代表您运行的SQL。

$db->getProfiler()->setEnabled(true);
$db->update( ... );
print $db->getProfiler()->getLastQueryProfile()->getQuery(); 
print_r $db->getProfiler()->getLastQueryProfile()->getQueryParams(); 
$db->getProfiler()->setEnabled(false);

以下是您具体问题的一些答案:

  • Zend_Db_Select::where('last_name=?', $lname)

    适当引用值。虽然“?”看起来像参数占位符,但在此方法中,参数实际上是适当引用并进行插值的。所以它不是一个真正的查询参数。实际上,以下两个语句产生与上述用法完全相同的查询:

    $select->where( $db->quoteInto('last_name=?', $lname) );
    $select->where( 'last_name=' . $db->quote($lname) );
    

    但是,如果传递的参数是Zend_Db_Expr类型的对象,则不会引用它。您负责SQL注入风险,因为它是逐字插入的,以支持表达式值:

    $select->where('last_modified < ?', new Zend_Db_Expr('NOW()'))
    

    该表达式中需要引用或分隔的任何其他部分是您的责任。例如,如果您将任何PHP变量插入到表达式中,则安全是您的责任。如果列名是SQL关键字,则需要使用quoteIdentifier()自行分隔。例如:

    $select->where($db->quoteIdentifier('order').'=?', $myVariable)
    
  • Zend_Db_Adapter_Abstract::insert( array('colname' => 'value') )

    表名称和列名称是分隔的,除非您关闭AUTO_QUOTE_IDENTIFIERS

    将值参数化为真实查询参数(未插入)。除非该值是Zend_Db_Expr对象,在这种情况下,它是逐字插值的,因此您可以插入表达式或NULL或其他任何内容。

  • Zend_Db_Adapter_Abstract::update( array('colname' => 'value'), $where )

    表名称和列名称是分隔的,除非您关闭AUTO_QUOTE_IDENTIFIERS

    值是参数化的,除非它们是Zend_Db_Expr个对象,如insert()方法。

    $where参数根本没有被过滤,所以你要对那个中的任何SQL注入风险负责。您可以使用quoteInto()方法来帮助引用更方便。

答案 1 :(得分:5)

是。见http://framework.zend.com/manual/en/zend.db.select.html。别担心。你是对的持怀疑态度。

答案 2 :(得分:2)

默认情况下,在SQL查询中使用值绑定时,如下所示:

where('first_name=?', $id);

Zend_Db使用适当的值引用来防止SQL注入。虽然强烈建议(通过书籍,文章,手册和自我体验)清理/过滤用户输入。 Zend_Filter非常有用。

答案 3 :(得分:1)

应该让你觉得安全的是?在where子句中标记。这些参数由数据库系统安全地替换为第二个参数。

答案 4 :(得分:1)

如果您在其他地方需要它(例如在加入中)或者您不确定它是否会被转义,那么您可以随时使用$this->getAdapter()->quoteInto('type = ?',1);

答案 5 :(得分:0)

过滤输入始终是好的,因为它可能会在除了数据库之外的其他地方,并且您至少需要在某个级别的数据库中获得理智的数据。

  • Zend_Filter_Input正在进行中
  • 准备好的陈述(如果没有准备好,则为quoteInto)
  • 逃离过滤器(htmlentities等)。

答案 6 :(得分:0)

有一点是,当值为NULL时,您可以获得无效的查询

$value = NULL;
$select->where('prop=?', $value);

结果:SQL错误