При соединении таблиц я использую модели 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§ion=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.
Вопросов:
- Как лучше всего предотвратить такой сценарий?
- Теперь я переживаю за предыдущих клиентов. Возможно ли с помощью этого кода совершить еще более рискованные действия, например, delate или alter table? Я думаю, не потому, что вы не можете поместить любой другой оператор, кроме SELECT внутри подвыбора, так что DELETE приведет к ошибке синтаксиса sql. Я прав?
ОБНОВЛЕНИЕ: Мой пример не является правильной иллюстрацией SQL-инъекции, потому что есть знак «$» вокруг разделов и, следовательно, сделать инъекцию невозможно. В любом случае это будет возможно при ожидании целочисленного значения и когда вы не фильтруете целочисленный ввод. Смотрите мой комментарий ниже.
источник
$db = Mage::getSingleton('core/resource')->getConnection('core_read');
и$db->quote()
даже в вашем случае посмотрите на$db->quoteInto
. Если$this
это ресурс, вы могли бы сделать:$this->getConnection('core_read')->quoteInto()
если это собрание можно сделать:$this->getResource()->getConnection('core_read')->quoteInto()
. вдоль этих линий. Если это поможет вам достичь цели.'
перед(
знаком всегда будет стоять знак, и поэтому(SELECT
или что-то еще будет просто строкой, а не функцией. Если поле является целым числом, то'
оно не нужно, и это делает возможным такой сценарий. Но целое число всегда должно быть отфильтровано,intval()
так что это тоже не проблема.'
? Так что' AND (SELECT ...) '
? Кстати, я не думаю, что Zend не цитирует это ... И если вы используете привязки, то PDO справится с этим. Просто никогда не используйте жало конкатенации, как это:"sections.section= '$section'"
Ответы:
Подтвердите ваш вклад!
Как хорошо и так много, как вы можете.
Некоторые предложения для вашей проверки:
Проверьте длину переменной, которую вы получите через GET-параметр. Нет необходимости принимать бесконечные длинные строки.
Подтвердите для доменного имени. Какой формат у ваших ожидаемых доменных имен? Это всегда www.mydomain.tld? Создайте регулярное выражение, которое проверяет совпадение или (лучше) использует
Zend_Validate_Hostname
:Белый список: знаете ли вы, какие доменные имена ожидать? Вы можете создать список разрешенных доменов и проверить их. Оставь остальные.
Включение в черный список доменных имен и / или символов: если вы ожидаете доменное имя, нет необходимости принимать любые другие символы, кроме az и 0-9 и "." (если вы не работаете со специальными доменными именами).
источник