小编典典

避免使用Zend_Db类进行MySQL注入

mysql

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

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

假设Zend_Db可以,我在不清理输入的情况下完成了此操作。Zend会这样做吗?

另一个问题:Zend_Db是否清除insert('table', $data)update查询?

谢谢。


阅读 285

收藏
2020-05-17

共1个答案

小编典典

当我是该项目的团队负责人(直到1.0版)时,我在Zend Framework中编写了很多用于数据库参数和引用的代码。

我尽力鼓励最佳做法,但必须在易用性之间取得平衡。

请注意,您始终可以检查Zend_Db_Select对象的字符串值,以了解其决定引用的方式。

print $select; // invokes __toString() method

您也可以使用Zend_Db_Profiler来检查由代表您运行的SQL Zend_Db

$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) );

但是,如果传递的参数是类型为object的对象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()方法使报价更加方便。

2020-05-17