Вопрос по безопасности SQL-запросов

verfaa

Профессор
Регистрация
29 Янв 2007
Сообщения
416
Реакции
49
Всегда обрабатывал строковые переменные в SQL-запросах ф-ей mysql_real_escape_string(), числовые - intval.
Недавно мне попал в руки скрипт, в котором программист заключает переменные в SQL-запросах просто в { }
Например, такой запрос
SELECT COUNT(*) FROM contacts WHERE user_id = {$user} AND folder_id = {$folder}
насколько безопасен?
Почему переменные не обрабатываются intval? В этом запросе есть SQL-уязвимость?

И ещё несколько вопросов по SQL:
Нужно обрабатывать переменные только пришедшие извне (из GET POST и т.д.) или абсолютно все переменные, которые присутствуют в запросе? (Даже те которые устанавливаются в теле скрипта, например $user_id = 28473;)

И ещё, есть ли разница и какой вариант лучше выбрать?
1) SELECT COUNT(*) FROM contacts WHERE user_id = '".intval($user_id)."'

2)
$user = intval($user_id);
SELECT COUNT(*) FROM contacts WHERE user_id = '".$user."'

Работаю с БД MySQL
 
Последнее редактирование:
На сколько мне известно структура {$user} применяется с двойными кавычками. Знаки {} говорят интерпритатору php о том, что в них точно находится переменная, в которую нужно вставить соответствующее значение.

Исходя из этого, код без экранирования параметров - дырявый. Можно сделать sql иньекцию.

И ещё, есть ли разница и какой вариант лучше выбрать?
1) SELECT COUNT(*) FROM contacts WHERE user_id = '".intval($user_id)."'
Этот лучше. По крайней мере в выборку попадет только числовое значение параметра.

Проверять нужно все параметры, пришедшие от пользователя: пост, гет запросы, куки, иногда сессии. Для программистов - параноиков - лучше обрабатывать полностью все входящие параметры. Может получиться так, что часть параметра берется из другой таблицы и без обработки теоретически будет возможна иньекция.
 
через mysql_real_escape_string() должны обрабатываться 100% передаваемых в запрос параметров.. безотносительно источника их происхождения.. точка..
 
через mysql_real_escape_string() должны обрабатываться 100% передаваемых в запрос параметров.. безотносительно источника их происхождения.. точка..
Да? А в prepared statements тоже надо обрабатывать mysql_real_escape_string() ?
 
давайте ещё postgresql, oracle, mssql и т.п. вспомните.. тут речь явно о модуле mysql.. prepared statements в нем нет..
 
советую использовать PDO
 
И ещё, есть ли разница и какой вариант лучше выбрать?
1) SELECT COUNT(*) FROM contacts WHERE user_id = '".intval($user_id)."'

2)
$user = intval($user_id);
SELECT COUNT(*) FROM contacts WHERE user_id = '".$user."'

Два варианта одинаковы по защищенности. Какой больше нравится стиль написания тот и используйте.
Я обычно для красоты кода, второй вариант использую.

А вообще читайте Для просмотра ссылки Войди или Зарегистрируйся. Много интересного можно узнать:)
 
А если переменная текст, разве в таком случае последними двумя вариантами нельзя сделать инъекцию?
 
Если переменная текст то intval от неё будет 0. Инъекцию можно сделать теоретически и для первого и второго варианта, т.к. в примерах в запрос идёт не сама переменная, а intval от неё, а она сама не меняется. Например, инъекция может быть, если user_id где то потом (в коде) пойдёт в запрос без интвала и переменная $user_id получилась из пользовательского ввода. Допустим, в адресной строке user_id=8 union select 1, тогда intval($user_id)=8 а сама переменная не убивается и union в ней путешествует от запроса к запросу
 
Используйте PDO и prepared statements - будет вам счастье.
 
Назад
Сверху