Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > SQL инъекция


Автор: Ripper 1.4.2013, 16:24
Добрый вечер.

Допустим, имеется URL: site.ru/image/get/5/, где 5 - айдишник картинки.
На сервере ничего не фильтруется, 
Код

$result = db::query("SELECT * FROM img WHERE id = '$id'");


Как здесь провести инъекцию? Вот почитал примеры, типа можно приписать WHERE id='5' OR 'x'='x', и можно вытащить все картинки например. Но ведь если парсится URL, то пробел заменяется на %20, и в запрос идет %20 вместо пробела, и выскакивает ошибка на получении данных ($data = $result->fetch_array(), но $data = false)

Если id передавался бы как get параметр, то тогда все получается, а в случае если парсится url? 

Спасибо.

Автор: Arantir 1.4.2013, 18:45
Цитата(Ripper @  1.4.2013,  15:24 Найти цитируемый пост)
Но ведь если парсится URL, то пробел заменяется на %20, и в запрос идет %20 вместо пробела

А вы уверены? То есть, нет ли где-то там обратной конвертации ссылки в текст? Чтобы могли работать ссылки на подобии /user/Иван, ведь не во всех случаях можно заменить кириллические символы латинскими.

Не каждый запрос является потенциальной дырой. Чтобы выбрать что-то из БД надо знать ее структуру. И то не факт, что даже при успешном запросе это будет выведено на экран, например, если php выводит данные по названиям полей, то надо как минимум подменить их аналогичными алиасами в злополучном запросе, иначе они просто пройдут мимо вывода.
Кроме того, на СУБД есть неплохая система прав и полномочий. Обычно СУБД-пользователю, которым пользуется сайт, совершенно не нужно иметь прав на вывод списка таблиц, удаление таблиц и подобное, а уж тем более доступа к базам 'mysql' и 'information_schema'. Так что и узнать структуру БД с помощью инъекции может не представляться физически возможным.

Пример явной дыры, это что-то вроде:
Код
SELECT * FROM users WHERE login = '$login' AND password = '$password'
где апостроф + знак комментария после логина позволит авторизироваться без пароля, ведь эти символы передаются в неизменном виде по ссылке. И никаких пробелов не нужно.

Тем не менее, разумным является создание запросов, в которых невозможно вообще ничего, кроме заранее предусмотренного разработчиком. Например, допустим, значение фильтруется как числовое. А что будет, если ввести туда 999999999999999? В лучшем из плохих случаев будет ошибка php, а в худшем может и ошибка SQL с куском запроса и названиями полей и таблиц.
Кстати, старые добрые предподготовленные запросы спасают сразу от многих проблем. Штука, поверенная временем =)

Автор: Aliance 2.4.2013, 10:11
Цитата(Arantir @  1.4.2013,  19:45 Найти цитируемый пост)
Например, допустим, значение фильтруется как числовое. А что будет, если ввести туда 999999999999999? В лучшем из плохих случаев будет ошибка php, а в худшем может и ошибка SQL с куском запроса и названиями полей и таблиц.

Эм, точно? Ввел число 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 - ничего плохого не произошло, написало лишь что rowset не найден.

Автор: Arantir 2.4.2013, 18:39
Цитата(Aliance @  2.4.2013,  09:11 Найти цитируемый пост)
Эм, точно?

А о точности утверждения сказано во второй части процитированного вами фрагмента =)
Но если бы сам не встречал подобной проблемы — не писал бы.

Автор: Gold Dragon 3.4.2013, 07:41
Цитата(Ripper @  1.4.2013,  17:24 Найти цитируемый пост)
Как здесь провести инъекцию?
а зачем?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)