Уязвимости SQL-инъекций при использовании SQL-моделей Zend Framework

15

При соединении таблиц я использую модели SQL Zend Framework. В качестве примера я изменил свой реальный код, но я думаю, вы поймете:

$this->getSelect()->join(
                      array('sections' => $sectionsTableName),
                      'main_table.banner_id = pages.banner_id',
                      array()
                    )
                  ->where("sections.section= '$section' OR sections.section = '0' OR (sections.section = '6' AND ? LIKE main_table.url)",$url)
                  ->group('main_table.banner_id'); 

Страница загружается с помощью ajax, а параметр $ section отправляется как параметр GET ( www.example.com/controllerName/index/display/3?paremeter1=example&section=www.example2.com).

Теперь вот проблема, если кто-то выполняет что-то вроде этого:

www.example.com/controllerName/index/display/3?paremeter1=example&url=(SELECT 3630 FROM(SELECT COUNT(*),CONCAT(0x7170786a71,(SELECT (ELT(3630=3630,1))),0x717a716b71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)

Таким образом, пользователь может сбросить всю базу данных. Данные не будут отображаться, но SQL все равно выполнит дамп, который может вызвать перегрузку sql.

Вопросов:

  1. Как лучше всего предотвратить такой сценарий?
  2. Теперь я переживаю за предыдущих клиентов. Возможно ли с помощью этого кода совершить еще более рискованные действия, например, delate или alter table? Я думаю, не потому, что вы не можете поместить любой другой оператор, кроме SELECT внутри подвыбора, так что DELETE приведет к ошибке синтаксиса sql. Я прав?

ОБНОВЛЕНИЕ: Мой пример не является правильной иллюстрацией SQL-инъекции, потому что есть знак «$» вокруг разделов и, следовательно, сделать инъекцию невозможно. В любом случае это будет возможно при ожидании целочисленного значения и когда вы не фильтруете целочисленный ввод. Смотрите мой комментарий ниже.

JohnyFree
источник
1
Вы можете использовать: $db = Mage::getSingleton('core/resource')->getConnection('core_read');и $db->quote()даже в вашем случае посмотрите на $db->quoteInto. Если $thisэто ресурс, вы могли бы сделать: $this->getConnection('core_read')->quoteInto()если это собрание можно сделать: $this->getResource()->getConnection('core_read')->quoteInto(). вдоль этих линий. Если это поможет вам достичь цели.
зола
Я просто понял, что этот сценарий возможен, только если значение является целым числом. Если значением является varchar, то 'перед (знаком всегда будет стоять знак, и поэтому (SELECTили что-то еще будет просто строкой, а не функцией. Если поле является целым числом, то 'оно не нужно, и это делает возможным такой сценарий. Но целое число всегда должно быть отфильтровано, intval()так что это тоже не проблема.
JohnyFree
Что если вы начнете с закрытия '? Так что ' AND (SELECT ...) '? Кстати, я не думаю, что Zend не цитирует это ... И если вы используете привязки, то PDO справится с этим. Просто никогда не используйте жало конкатенации, как это:"sections.section= '$section'"
7очев
@ 7ochem в таком случае вы ДОЛЖНЫ связать параметр, используя? и «станет \». Но если вы используете целочисленное значение, то вы не связывать его , так как вы можете очистить его с помощью intval () функции PHP и «что - то будет 0.
JohnyFree

Ответы:

8

Подтвердите ваш вклад!

Как хорошо и так много, как вы можете.

Некоторые предложения для вашей проверки:

  1. Проверьте длину переменной, которую вы получите через GET-параметр. Нет необходимости принимать бесконечные длинные строки.

  2. Подтвердите для доменного имени. Какой формат у ваших ожидаемых доменных имен? Это всегда www.mydomain.tld? Создайте регулярное выражение, которое проверяет совпадение или (лучше) использует Zend_Validate_Hostname:

    $validator = new Zend_Validate_Hostname();
    if ($validator->isValid($hostname)) {
        //hostname is valid - continue
    }
  3. Белый список: знаете ли вы, какие доменные имена ожидать? Вы можете создать список разрешенных доменов и проверить их. Оставь остальные.

    $allowedDomains = array('www.domain1.tld','www.domain2.tld');
  4. Включение в черный список доменных имен и / или символов: если вы ожидаете доменное имя, нет необходимости принимать любые другие символы, кроме az и 0-9 и "." (если вы не работаете со специальными доменными именами).

Анна Фёлькл
источник