A web developer's blog. PHP, MySQL, CakePHP, Zend Framework, Wordpress, Code Igniter, Django, Python, CSS, Javascript, jQuery, Knockout.js, and other web development topics.

Zend Framework: SQL Injection Prevention from DPC Slides

I would never make it to any PHP Conference, so I would have to be satisfied by the replays and slides. I got these from the DPC slides found here (pdf).

function query($sql, $bind = array())

- uses prepared statement internally
- SQL Injection still possible if $sql is dynamically created

function fetchAll($sql, $bind = array(), $fetchMode = null)

- all “fetch” methods use prepared statements internally
- SQL Injection still possible if $sql is dynamically created

<?php
$sql = "SELECT id FROM users WHERE lastname=? AND age=?";
$params = array('Smith','18');
$result = $db->fetchAll($sql, $params);
?>

More stufff…

function insert($table, array $bind)

- internally uses prepared statements
- SQL-Injection not possible

function update($table, array $bind, $where = '')

- uses partially prepared statements
- SQL-Injection still possible if $where is dynamically created

function delete($table, $where = '')

- SQL-Injection still possible if $where is dynamically created

Zend_Db – Escaping

function quote($value, $type = null)

- applies the correct escaping – one function not many
- ATTENTION: also puts strings in quotes
Note: If the type of your field in your database is an Integer, then I would suggest that you use a second parameter — see below.

$value = '1234';
$sql = 'SELECT * FROM atable WHERE intColumn = '. $this->_db->quote($value, 'INTEGER');


function quoteIdentifier($ident, $auto=false)

- applies escaping for identifiers
- a function not available to traditional PHP applications
- ATTENTION: also puts strings in quotes
- Used for table names, columns, and other identifiers in SQL statements

If you use PHP variables to name tables, columns, or other identifiers in your SQL statements, you might need to quote these strings too.

Example:

class Default_Model_DbTable_Ordertype extends Zend_Db_Table_Abstract
{
    /** Table name */
    protected $_name = 'order_type';
 
    public function init()
    {
        $this->_db->setFetchMode(Zend_Db::FETCH_OBJ);
    }
 
    public function fetchAll($country_id)
    {
        $sql = 'SELECT *
                FROM
                '.$this->_name.'
                WHERE order_type_status = "on"
                AND country_id = ?';
 
        return $this->_db->fetchAll($sql,array($country_id));
    }
 
    public function fetchAllQuoted($country_id)
    {
        /**
         * This would also work.
         * But I prefer the one above.
         * It is shorter and easier to read.
         * Both will have the same results.
         */
        $country_id = $this->_db->quote($country_id);
        $sql = 'SELECT *
                FROM
                '.$this->_name.'
                WHERE order_type_status = "on"
                AND country_id = '.$country_id;
 
        /**
         * No second parameter.
         */
        return $this->_db->fetchAll($sql);
    }
}

MORE UPDATES:
Note that quote() and quoteInto() is a method of Zend_Db_Adapter_Abstract. So if you need to use it within your Mapper (like the models in ZF1.8 Quickstart), then you need to use the getAdapter() method:

<?php
 
class Twitter_Model_GroupMapper
{
    protected $_dbTable;
 
    public function setDbTable($dbTable)
    {
        if (is_string($dbTable)) {
            $dbTable = new $dbTable();
        }
        if (!$dbTable instanceof Zend_Db_Table_Abstract) {
            throw new Exception('Invalid table data gateway provided');
        }
        $this->_dbTable = $dbTable;
        return $this;
    }
 
    public function getDbTable()
    {
        if (null === $this->_dbTable) {
            $this->setDbTable('Twitter_Model_DbTable_Group');
        }
        return $this->_dbTable;
    }
 
    public function fetchGroup($twitter_username)
    {
        $quoted = $this->getDbTable()->getAdapter()->quote($twitter_username); //HERE!!!
        $resultSet = $this->getDbTable()->fetchAll('twitter_name = '.$quoted.'');
        return $resultSet;
    }
}
This entry was posted in General and tagged , , , , , . Bookmark the permalink.

3 Responses to Zend Framework: SQL Injection Prevention from DPC Slides

  1. Pingback: Security Threat Beware: iFrame Injection Attacks | The Geek Web

  2. typothief says:

    there is a typo:

    fetchAll($sql, $params);
    ?>

    3rd line should be $params = array(‘Smith’,’18′);

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>