14

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.

daniel
  • 1,212
  • 1
  • 18
  • 33

7 Answers7

24

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.

Bill Karwin
  • 538,548
  • 86
  • 673
  • 828
  • Great answer, Bill, and a great component all round :) – David Snabel-Caunt Jun 21 '09 at 13:02
  • If you use the `insert()` function on an instance of `TableGateway`, escaping of columns with reserved names are automatically done for you as said in the second bullet above. If you manually escape it (i.e.(SQL Server) `array ( [from] => 1 ));` it produces a database error that says `'[from]'` is an invalid column name. That column might have been escaped twice as `[[from]]` – leonard.javiniar Jul 20 '16 at 08:45
4

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

Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
2

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.

farzad
  • 8,775
  • 6
  • 32
  • 41
1

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.

David Snabel-Caunt
  • 57,804
  • 13
  • 114
  • 132
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);

Tomáš Fejfar
  • 11,129
  • 8
  • 54
  • 82
0

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).
Justin
  • 5,029
  • 1
  • 21
  • 21
0

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

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

Result: SQL error

danronmoon
  • 3,814
  • 5
  • 34
  • 56
duganets
  • 1,853
  • 5
  • 20
  • 31
  • In SQL, you can't use the = operator to compare to NULL anyway. – Bill Karwin Jun 21 '09 at 15:06
  • my example not about NULL-values, i try to show that in some cases you need check/convert type of values to pass in sql-query build functions, this is in context of discussion – duganets Jun 23 '09 at 13:42