使用 Zend_Db 类避免 MySQL 注入

发布于 2024-07-24 09:52:22 字数 387 浏览 12 评论 0原文

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

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

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

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

谢谢。

I currently use Zend_Db to manage my queries.
I've written already code that preforms queries like the one below:

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

I've done this without sanitizing the input, assuming Zend_Db will. Does Zend do this?

Another question:
Does Zend_Db sanitize insert('table', $data) and update queries?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

不必你懂 2024-07-31 09:52:22

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

我试图尽可能鼓励最佳实践,但我必须在易用性之间取得平衡。

请注意,您始终可以检查 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() 方法来帮助使引用更加方便。

I wrote a lot of the code for database parameters and quoting in Zend Framework while I was the team lead for the project (up to version 1.0).

I tried to encourage best practices where possible, but I had to strike a balance with ease of use.

Note that you can always examine the string value of a Zend_Db_Select object, to see how it has decided to do quoting.

print $select; // invokes __toString() method

Also you can use the Zend_Db_Profiler to inspect the SQL that is run on your behalf by Zend_Db.

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

Here are some answers to your specific questions:

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

    Values are quoted appropriately. Although the "?" looks like a parameter placeholder, in this method the argument is actually quoted appropriately and interpolated. So it's not a true query parameter. In fact, the following two statements produce exactly the same query as the above usage:

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

    However, if you pass a parameter that is an object of type Zend_Db_Expr, then it's not quoted. You're responsible for SQL injection risks, because it's interpolated verbatim, to support expression values:

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

    Any other part of that expression that needs to be quoted or delimited is your responsibility. E.g., if you interpolate any PHP variables into the expression, safety is your responsibility. If you have column names that are SQL keywords, you need to delimit them yourself with quoteIdentifier(). Example:

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

    Table name and column names are delimited, unless you turn off AUTO_QUOTE_IDENTIFIERS.

    Values are parameterized as true query parameters (not interpolated). Unless the value is a Zend_Db_Expr object, in which case it's interpolated verbatim, so you can insert expressions or NULL or whatever.

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

    Table name and column names are delimited, unless you turn off AUTO_QUOTE_IDENTIFIERS.

    Values are parameterized, unless they are Zend_Db_Expr objects, as in insert() method.

    The $where argument is not filtered at all, so you're responsible for any SQL injection risks in that one. You can make use of the quoteInto() method to help make quoting more convenient.

假扮的天使 2024-07-31 09:52:22

是的。 请参阅 http://framework.zend.com/manual/en/zend .db.select.html 。 不用担心。 你的怀疑是对的。

Yes. See http://framework.zend.com/manual/en/zend.db.select.html . Don't worry. You're right to be skeptical.

白龙吟 2024-07-31 09:52:22

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

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

Zend_Db 使用适当的值引用来防止 SQL 注入。 尽管强烈建议(通过书籍、文章、手册和自身经验)清理/过滤用户输入。 Zend_Filter 非常有帮助。

by default when you use value binding in your SQL queries like this:

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

Zend_Db uses appropriate quoting of values to prevent SQL injection. although it is strongly recommended (by books, articles, manuals and self experience) to sanitize/filter user input. Zend_Filter can be very helpful.

千柳 2024-07-31 09:52:22

应该让您感到安全的一点是? where 子句中的标记。 这些是参数,由数据库系统安全地替换为第二个参数。

The bit that should make you feel safe is the ? marks in the where clauses. These are parameters, which are safely replaced with the second argument by the database system.

阪姬 2024-07-31 09:52:22

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

When you need it somewhere else (like in join) or you are unsure if it will be escaped then you can always use $this->getAdapter()->quoteInto('type = ?',1);

浅听莫相离 2024-07-31 09:52:22

过滤输入总是好的,因为它很可能会进入数据库以外的其他地方,并且您至少希望数据库中的数据在某种程度上保持正常。

  • Zend_Filter_Input
  • 准备好的语句中(如果不在准备好的语句中,则为 quoteInto)
  • 在退出的路上转义过滤器(htmlentities 等)。

Filtering input is always good, because likely it'll be going somewhere other than just the DB, and you at least want sane data in your database at some level.

  • Zend_Filter_Input on the way in
  • Prepared statements (or quoteInto if not in a prepared)
  • Escape filters on the way out (htmlentities, etc).
百合的盛世恋 2024-07-31 09:52:22

关于这一点的一件事是,当值为 NULL 时,您可以实现无效查询

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

结果:SQL 错误

One thing about this, when value is NULL, you can achieve not valid query

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

Result: SQL error

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文