избегать инъекций MySQL с помощью класса Zend_Db - PullRequest
14 голосов
/ 10 июня 2009

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

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

Я сделал это без очистки входных данных, предполагая, что Zend_Db сделает это. Зенд делает это?

Еще один вопрос: Обрабатывает ли Zend_Db запросы insert('table', $data) и update?

Спасибо.

Ответы [ 7 ]

24 голосов
/ 12 июня 2009

Я написал много кода для параметров базы данных и цитирования в 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(), чтобы сделать цитирование более удобным.

5 голосов
/ 10 июня 2009

Да. См. http://framework.zend.com/manual/en/zend.db.select.html. Не беспокойся Вы правы быть скептиком.

2 голосов
/ 10 июня 2009

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

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

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

1 голос
/ 10 июня 2009

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

1 голос
/ 10 июня 2009

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

0 голосов
/ 11 июня 2009

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

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

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

0 голосов
/ 11 июня 2009

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

  • Zend_Filter_Input в пути
  • Подготовленные заявления (или цитата, если не в подготовленном)
  • Выходные фильтры на выходе (htmlentities и т. Д.).
...