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

ggfdsfds

Новичок
Только узнал, что есть такое понятие как SQL-иньекции в PHP.
И не совсем пойму - приводят пример:

PHP:
// Пример запроса
$pageId = $_GET['page_id'];
mysql_query(" SELECT * FROM page WHERE id=" . $pageId);

// И вот пример иньекции:
// человек передает в адресной строке браузера: ?page_id=5;DELETE FROM users;
$pageId = $_GET['page_id'];
mysql_query(" SELECT * FROM page WHERE id=" . $pageId);
В итоге получаем запрос вида
SELECT * FROM page WHERE id=5; DELETE FROM users;

Как этот-то запрос может быть выполнен?
Когда во первых mysql_query() - может выполнить только один запрос, и соответственно ";" - уже есть два запроса, что приведет к ошибке? Тот же phpmyadmin - такие запросы разбивает на два запроса и выполняет их по отдельности.

Так понимаю, что иньекции делают только как вложенные запросы?
Или что-то понимаю не правильно...
Очень бы хотелось разрабатывать более менее грамотные приложения...

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

WMix

герр M:)ller
Партнер клуба
Код:
?page_id=null union select id, pass as page_name from users where nick='administrator'
 

ggfdsfds

Новичок
Спасибо за материал - читаю.

Код:
?page_id=null union select id, pass as page_name from users where nick='administrator'
Идею понял - что вместо названия страницы будет выведен пароль пользователя, который скорее всего будет в MD5.
 

Vladson

Сильнобухер
Ты не "что-то понимаю неправильно" а всё вообще не понял... Вопрос не в том что нужно "обезопасить приложение" нужно изначально писать код так чтоб он делал то что он должен делать, НО И ОБЯЗАТЕЛЬНО чтоб он не делал то чего делать недолжен !!!!

Т.е если вы делаете запрос типа mysql_query(" SELECT * FROM page WHERE id=" . $pageId); то вам надо убедиться что $pageId это именно "page Id" и вам не надо ничего фильтровать или обезопасивать, вам надо просто убедиться что данные пришли верно и не повредились по пути !!! (ну или не были подменены злоумышленником)
 

ggfdsfds

Новичок
Читая статью, нашел -
http://phpfaq.ru/SafeMysql

На данный момент библиотека поддерживает 6 плейсхолдеров. Это:

- ?s ("string") - строки (а также DATE, FLOAT и DECIMAL).
- ?i ("integer") - целые числа.
- ?n ("name") - имена полей и таблиц
- ?p ("parsed") - для вставки уже обработанных частей запроса
- ?a ("array") - набор значений для IN (строка вида 'a','b','c')
- ?u ("update") - набор значений для SET (строка вида `field`='value',`field`='value')

Получается, что если это использовать - то иньекция с UNION - уже не пройдет?
 

Фанат

oncle terrible
Команда форума
ты неправильно понимаешь, что такое инъекция.
В сказке про Буратино есть такой эпизод: Мальвина задаёт ему задачку, "Допустим, у тебя есть 5 яблок. потом некто взял у тебя два..." Буратино возмущается, "не дам я Некту два я яблока, хоть он дерись!". Всё - задача решена.
Ты точно такая же буратина - "вот этот конкретный пример с инъекцией не работает - всё, защищаться ни от чего не надо!". Тебе показывают другой - ты тут же пугаешься и начинаешь метаться в происках защиты. А всё потому, что
НЕ НАДО БЫЛО ИЗНАЧАЛЬНО ПРОСИТЬ ПРИМЕР ИНЪЕКЦИИ
потому что пример - это просто пример. демонстрация механизма.
практических же реализаций - миллион. Не надо защищаться от каждой по отдельности.
Не надо спрашивать, защищен ли твой код от той или иной инъекции.
код бывает или защищен - тогда он защищен от ЛЮБОЙ
или не защищен - тогда тебя поломают обязательно, ДАЖЕ если ты, в силу своей неграмотности, пути для взлома не видишь

Поэтому не бывает кода, защищенного "от иньекции с UNION". Бывает просто защищенный от инъекций.

До тех пор, пока ты ЛЮБЫЕ переменные помещаешь в запрос через плдейсхолдер, да - НИКАКАЯ инъекция не пройдет.
 

ggfdsfds

Новичок
Спасибо за ответ, разобрался с плейсхолдерами.
Как понял, с их помощью получится что-то вроде:

Код:
SELECT * FROM WHERE page_id = '12  union select id, pass as page_name from users where nick=\'administrator\''
Соответственно там, еще будет преобразование через mysql_real_escape_string, как понимаю (условно говоря), и весь параметр, который передается через _GET и подставляется в запрос MySQL- воспримет как значение - обернутое в кавычки ' '.

Еще раз спасибо за пояснение.
 

WMix

герр M:)ller
Партнер клуба
в данном случае нужно было преобразовать page_id в integer
 

WMix

герр M:)ller
Партнер клуба
да, алгоритм того, как превращается пароль в то что ты хранишь в базе
 

ggfdsfds

Новичок
А мне думалось, что MD5() - это более менее надежно...
Еще раз спасибо - взял на заметку.
 

WMix

герр M:)ller
Партнер клуба
Фанат, а разница? зарегестрироавлся, получил свой хэш, перебрал с учетом своего пароля, получил соль. вопрос только времени
 
Сверху