Избегая инъекций MySQL с классом Zend_Db

В настоящее время я использую Zend_Db для управления моими запросами. Я уже написал код, который обрабатывает запросы, подобные приведенным ниже:

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

Я сделал это без дезинфекции ввода, предполагая, что Zend_Db будет. Zend делает это?

Другой вопрос: Zend_Db дезинфицирует запросы insert('table', $data) и update?

Спасибо.

Ответы

Ответ 1

Я написал много кода для параметров базы данных и цитирования в Zend Framework, когда я был руководителем команды для проекта (до версии 1.0).

Я старался поощрять лучшие практики там, где это было возможно, но мне приходилось просто балансировать с легкостью использования.

Обратите внимание, что вы всегда можете проверить строковое значение объекта 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) );
    

    Однако, если вы передаете параметр, являющийся объектом типа 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(), чтобы сделать предложение более удобным.

Ответ 3

по умолчанию, когда вы используете привязку значений в своих SQL-запросах следующим образом:

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

Zend_Db использует соответствующее цитирование значений для предотвращения SQL-инъекции. хотя настоятельно рекомендуется (по книгам, статьям, учебным пособиям и самому опыту) для дезинфекции/фильтрации ввода пользователя. Zend_Filter может быть очень полезным.

Ответ 4

Бит, который должен заставить вас чувствовать себя в безопасности, это? отмечает в предложениях where. Это параметры, которые безопасно заменяются вторым аргументом системой базы данных.

Ответ 5

Если вам это нужно где-то в другом месте (например, в соединении), или вы не уверены, будет ли он экранирован, вы всегда можете использовать $this->getAdapter()->quoteInto('type = ?',1);

Ответ 6

Вход для фильтрации всегда хорош, потому что, скорее всего, он будет куда-то иным, чем только БД, и вы по крайней мере хотите, чтобы в вашей базе данных были данные на некотором уровне.

  • Zend_Filter_Input по пути в
  • Подготовленные утверждения (или quoteInto, если они не подготовлены)
  • Фильтры Escape на выходе (htmlentities и т.д.).

Ответ 7

Одна вещь об этом, когда значение равно NULL, вы можете получить недействительный запрос

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

Результат: ошибка SQL